Skip to main content

Overview

The Timeback SDK supports two identity modes.

SSO Mode

SSO mode uses Timeback as the identity provider via OIDC. The SDK automatically resolves the Timeback user by email and returns TimebackAuthUser.
lib/timeback.ts
import { createTimeback } from '@timeback/sdk'

export const timeback = await createTimeback({
	env: 'staging',
	api: {
		clientId: process.env.TIMEBACK_API_CLIENT_ID!,
		clientSecret: process.env.TIMEBACK_API_CLIENT_SECRET!,
	},
	identity: {
		mode: 'sso',
		clientId: process.env.AWS_COGNITO_CLIENT_ID!,
		clientSecret: process.env.AWS_COGNITO_CLIENT_SECRET!,
		onCallbackSuccess: async ({ user, idp, state, redirect }) => {
			// user.id is the timebackId
			// user.email, user.name come from the user's Timeback profile
			// user.claims contains IdP data (sub, firstName, lastName, pictureUrl)
			await setSession({ id: user.id, email: user.email })
			return redirect(state?.returnTo ?? '/')
		},
		onCallbackError: ({ error, errorCode, redirect }) => {
			console.error('SSO Error:', errorCode, error.message)
			return redirect('/?error=sso_failed')
		},
		getUser: () => getCurrentSession(),
	},
})
The user object in onCallbackSuccess has this structure:
interface TimebackAuthUser {
	id: string // Timeback user ID
	email: string
	name?: string
	school?: { id: string; name: string }
	grade?: number
	claims: {
		sub: string
		email: string
		firstName?: string
		lastName?: string
		pictureUrl?: string
	}
}

Custom Mode

Use custom mode when your app has its own authentication system.
lib/timeback.ts
import { createTimeback } from '@timeback/sdk'

export const timeback = await createTimeback({
	env: 'staging',
	api: {
		clientId: process.env.TIMEBACK_API_CLIENT_ID!,
		clientSecret: process.env.TIMEBACK_API_CLIENT_SECRET!,
	},
	identity: {
		mode: 'custom',
		getEmail: async req => {
			const session = await getSession(req)

			// Return the email from your existing auth system
			return session?.email
		},
	},
})
The SDK resolves the Timeback user by email. You only need to provide the authenticated user’s email address.

Identity-Only Mode

If you need only SSO, use createTimebackIdentity():
lib/timeback.ts
import { createTimebackIdentity } from '@timeback/sdk'

export const timeback = createTimebackIdentity({
	env: 'production',
	identity: {
		mode: 'sso',
		clientId: process.env.AWS_COGNITO_CLIENT_ID!,
		clientSecret: process.env.AWS_COGNITO_CLIENT_SECRET!,
		onCallbackSuccess: async ({ user, tokens, redirect }) => {
			// user is raw OIDC userInfo (sub, email, name, picture, etc.)
			// No Timeback profile enrichment in identity-only mode
			await createSession({
				sub: user.sub,
				email: user.email,
				name: user.name,
			})
			return redirect('/')
		},
		onCallbackError: ({ error, redirect }) => {
			return redirect('/login?error=sso_failed')
		},
		getUser: req => getSessionFromRequest(req),
	},
})

Sign-In Flow

The SDK provides a SignInButton component that initiates the SSO flow:
import { SignInButton } from '@timeback/sdk/react'

function LoginPage() {
	return <SignInButton size="lg">Sign in with Timeback</SignInButton>
}

User Verification

Verify if a user has a Timeback account:
import { useTimebackVerification } from '@timeback/sdk/react'

function ProtectedContent() {
	const { state } = useTimebackVerification()

	if (state.status === 'loading') return <div>Loading...</div>
	if (state.status !== 'verified') return <div>Please sign in</div>

	return <div>Protected content</div>
}

Next Steps