Files
rudder-js-sdk/skills/rudder-web-sdk/reference/auth.md
T

174 lines
6.1 KiB
Markdown
Raw Normal View History

# Auth — `client.auth`
`AuthService` (source: `src/auth/AuthService.ts`). Player authentication:
device ID login (primary for game clients), Google / Apple sign-in, custom
webhook login, identity linking/unlinking, logout, and auth state observation.
## Methods
```ts
loginWithDevice(options?: LoginWithDeviceOptions): Promise<LoginViaDeviceResponse>
loginWithGoogle(options: LoginWithGoogleOptions): Promise<LoginViaGoogleResponse>
loginWithApple(options: LoginWithAppleOptions): Promise<LoginViaAppleResponse>
loginWithCustom(options: LoginWithCustomOptions): Promise<LoginViaCustomResponse>
linkWithGoogle(idToken: string): Promise<void>
linkWithApple(idToken: string): Promise<void>
linkWithCustom(options: LinkWithCustomOptions): Promise<void>
unlinkIdentity(provider: string): Promise<void>
logout(): void
get isAuthenticated(): boolean
onAuthStateChange(listener: AuthStateListener): () => void
```
### `LoginWithDeviceOptions`
```ts
{
region?: string; // default 'global'
language?: string; // default 'en'
nickname?: string; // omitted from the request when not set
}
```
The device ID is auto-generated on first call and persisted in localStorage
(`src/device/DeviceId.ts`). The request also carries the client's
`projectKey`.
### `LoginWithGoogleOptions` / `LoginWithAppleOptions`
```ts
{
idToken: string; // required — Google ID token / Apple identity token
region?: string; // default 'global'
language?: string; // default 'en'
nickname?: string; // omitted from the request when not set
}
```
The client obtains the `idToken` from the provider's own sign-in flow
(Google Identity Services, Sign in with Apple) and forwards it to
`POST /sdk/v1/authorization/google` or `/sdk/v1/authorization/apple`.
### `LoginWithCustomOptions`
```ts
{
customData: Record<string, unknown>; // required — forwarded to the project's custom auth webhook
provider?: string; // custom provider name; omitted = the default provider
region?: string; // default 'global'
language?: string; // default 'en'
nickname?: string;
}
```
### Login responses
```ts
interface LoginViaDeviceResponse { accessToken?: string; refreshToken?: string }
interface LoginViaGoogleResponse { accessToken?: string; refreshToken?: string }
interface LoginViaAppleResponse { accessToken?: string; refreshToken?: string }
interface LoginViaCustomResponse { accessToken?: string; refreshToken?: string }
```
On success both tokens are saved to the client's `TokenStore`, player and
catalog are warmed, the revision poll starts, and the state flips to
`'signed-in'`.
## Identity linking
`linkWithGoogle` / `linkWithApple` / `linkWithCustom` attach an additional
identity to the currently signed-in player; `unlinkIdentity` detaches one.
All four require an active session — the access token is sent automatically
(transport level). They return nothing (HTTP 204).
```ts
await client.auth.linkWithGoogle(idToken);
await client.auth.linkWithApple(idToken);
await client.auth.linkWithCustom({ customData, provider }); // provider optional
await client.auth.unlinkIdentity('custom:my-backend');
```
### `LinkWithCustomOptions`
```ts
{
customData: Record<string, unknown>; // required
provider?: string; // custom provider name; omitted = the default provider
}
```
`unlinkIdentity(provider)` takes the full provider string: `device`,
`google`, `apple`, `custom`, or `custom:<name>`.
Linked identities appear on the player profile:
`client.player.data.identities: PlayerProfileIdentity[]` with
`{ provider: string; subject: string; createdAt: string }`.
## Environments
A project has two environments, `staging` and `prod`. The SDK key you pass as
`RudderClientOptions.projectKey` belongs to one of them, so the environment is
resolved at login and carried inside the access and refresh tokens; nothing in
the client API takes an environment argument, and a player created in one
environment is invisible in the other. Content released only to `staging` is
empty for a `prod` key and vice versa.
Tokens issued before SDK 2.0.0 carry no environment claim and are rejected with
401. The transport's refresh then fails, clears the token store and emits
`'signed-out'` — log the player in again.
## Auth state
```ts
type AuthState = 'signed-in' | 'signed-out';
type AuthStateListener = (state: AuthState) => void;
```
- `isAuthenticated` is `true` while an access token is present in the token store.
- `onAuthStateChange` fires the listener **immediately** with the current state
and returns an unsubscribe function.
- `logout()` clears tokens, stops the revision poll, drops cached domain
data, and emits `'signed-out'`.
## Token refresh (automatic, transport level)
Source: `src/transport/request.ts`.
- Every request injects `Authorization: Bearer <accessToken>` when a token exists.
- On 401 the transport does a single-flight refresh against
`POST /sdk/v1/authorization/refresh` (concurrent 401s share one refresh) and
retries the original request once.
- If refresh fails, tokens are cleared, `onAuthStateChange` listeners get
`'signed-out'`, and the request throws `RudderAuthError`.
## TokenStore
```ts
interface TokenStore {
getAccessToken(): string | null;
getRefreshToken(): string | null;
saveTokens(accessToken: string, refreshToken: string): void;
clear(): void;
}
```
Factories (exported from the package root):
- `createDefaultTokenStore()` — localStorage, with a silent in-memory fallback
where localStorage is unavailable (SSR, private mode). This is the default
when `tokenStore` is omitted from `RudderClientOptions`.
- `createLocalStorageTokenStore()` — keys `rudder_access_token` /
`rudder_refresh_token`.
Provide a custom `TokenStore` via `RudderClientOptions.tokenStore` for other
backends (sessionStorage, cookies).
## Errors
- Constructor: missing `baseUrl`/`projectKey` → `RudderError`,
`code: 'sdk/invalid-options'`.
- Login failure → `RudderHttpError` (e.g. unknown project key) or
`RudderNetworkError`.
- Any later request with an expired session → `RudderAuthError` (after the
refresh attempt above fails).