> ## Documentation Index
> Fetch the complete documentation index at: https://docs.timeback.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity Modes

> Configure SSO or custom authentication with Timeback

## Overview

The Timeback SDK supports two identity modes.

<CardGroup cols={2}>
  <Card title="SSO" icon="key" href="#sso-mode">
    Use Timeback as your identity provider
  </Card>

  <Card title="Custom" icon="gear" href="#custom-mode">
    Use your existing auth system
  </Card>
</CardGroup>

## SSO Mode

SSO mode uses Timeback as the identity provider via OIDC. The SDK automatically resolves the Timeback user by email and returns `TimebackAuthUser`.

<CodeGroup>
  ```typescript TypeScript theme={null}
  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(),
  	},
  })
  ```

  ```python Python theme={null}
  from timeback.server import (
      create_server, TimebackConfig, ApiCredentials, SsoIdentityConfig,
  )

  async def get_user(request):
      session = await get_session(request)
      return {"id": session.user_id, "email": session.email}

  async def on_callback_success(ctx):
      # ctx.user["id"] is the timebackId
      # ctx.user["email"], ctx.user["name"] come from the user's Timeback profile
      await set_session(id=ctx.user["id"], email=ctx.user["email"])
      return ctx.redirect(ctx.state.get("return_to", "/"))

  def on_callback_error(ctx):
      return ctx.redirect("/?error=sso_failed")

  timeback = create_server(TimebackConfig(
      env="staging",
      api=ApiCredentials(
          client_id=os.environ["TIMEBACK_API_CLIENT_ID"],
          client_secret=os.environ["TIMEBACK_API_CLIENT_SECRET"],
      ),
      identity=SsoIdentityConfig(
          mode="sso",
          client_id=os.environ["TIMEBACK_SSO_CLIENT_ID"],
          client_secret=os.environ["TIMEBACK_SSO_CLIENT_SECRET"],
          get_user=get_user,
          on_callback_success=on_callback_success,
          on_callback_error=on_callback_error,
      ),
  ))
  ```
</CodeGroup>

The `user` object in `onCallbackSuccess` has this structure:

```typescript theme={null}
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.

<CodeGroup>
  ```typescript TypeScript theme={null}
  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
  		},
  	},
  })
  ```

  ```python Python theme={null}
  from timeback.server import (
      create_server, TimebackConfig, ApiCredentials, CustomIdentityConfig,
  )

  async def get_user_email(request):
      session = await get_session(request)

      # Return the email from your existing auth system
      return session.email if session else None

  timeback = create_server(TimebackConfig(
      env="staging",
      api=ApiCredentials(
          client_id=os.environ["TIMEBACK_API_CLIENT_ID"],
          client_secret=os.environ["TIMEBACK_API_CLIENT_SECRET"],
      ),
      identity=CustomIdentityConfig(
          mode="custom",
          get_email=get_user_email,
      ),
  ))
  ```
</CodeGroup>

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()`:

```typescript lib/timeback.ts theme={null}
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:

<Tabs>
  <Tab title="React">
    ```tsx theme={null}
    import { SignInButton } from '@timeback/sdk/react'

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

  <Tab title="Vue">
    ```vue theme={null}
    <script setup>
    import { SignInButton } from '@timeback/sdk/vue'
    </script>

    <template>
    	<SignInButton size="lg">Sign in with Timeback</SignInButton>
    </template>
    ```
  </Tab>

  <Tab title="Svelte">
    ```svelte theme={null}
    <script>
    	import { SignInButton } from '@timeback/sdk/svelte'
    </script>

    <SignInButton size="lg">Sign in with Timeback</SignInButton>
    ```
  </Tab>

  <Tab title="Solid">
    ```tsx theme={null}
    import { SignInButton } from '@timeback/sdk/solid'

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

## User Verification

Verify if a user has a Timeback account:

<Tabs>
  <Tab title="React">
    ```tsx theme={null}
    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>
    }
    ```
  </Tab>

  <Tab title="Vue">
    ```vue theme={null}
    <script setup>
    import { useTimebackVerification } from '@timeback/sdk/vue'

    const { state } = useTimebackVerification()
    </script>

    <template>
    	<div v-if="state.status === 'loading'">Loading...</div>
    	<div v-else-if="state.status !== 'verified'">Please sign in</div>
    	<div v-else>Protected content</div>
    </template>
    ```
  </Tab>

  <Tab title="Svelte">
    ```svelte theme={null}
    <script>
    	import { timebackVerification } from '@timeback/sdk/svelte'
    </script>

    {#if $timebackVerification.status === 'loading'}
    	<div>Loading...</div>
    {:else if $timebackVerification.status !== 'verified'}
    	<div>Please sign in</div>
    {:else}
    	<div>Protected content</div>
    {/if}
    ```
  </Tab>

  <Tab title="Solid">
    ```tsx theme={null}
    import { Show } from 'solid-js'
    import { createTimebackVerification } from '@timeback/sdk/solid'

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

    	return (
    		<Show when={state.status === 'verified'} fallback={
    			<Show when={state.status === 'loading'} fallback={<div>Please sign in</div>}>
    				<div>Loading...</div>
    			</Show>
    		}>
    			<div>Protected content</div>
    		</Show>
    	)
    }
    ```
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={2}>
  <Card title="Custom Activities" icon="chart-line" href="/beta/build-on-timeback/sdk/activity-tracking/intro">
    Track learning sessions
  </Card>

  <Card title="User Profile" icon="id-card" href="/beta/build-on-timeback/sdk/user-profile">
    Access user data and XP
  </Card>

  <Card title="Server Adapters" icon="server" href="/beta/build-on-timeback/sdk/server/nextjs">
    Framework integration
  </Card>

  <Card title="Client Adapters" icon="browser" href="/beta/build-on-timeback/sdk/client/react">
    Client components
  </Card>
</CardGroup>
