feat(auth): Google/Apple login, named custom providers, identity link/unlink
CI / check (push) Successful in 16s
CI / publish (push) Has been skipped

This commit is contained in:
edmand46
2026-09-08 16:05:00 +03:00
parent 7271874cac
commit f45261439f
8 changed files with 293 additions and 10 deletions
+56 -2
View File
@@ -1,14 +1,20 @@
# Auth — `client.auth`
`AuthService` (source: `src/auth/AuthService.ts`). Player authentication:
device ID login (primary for game clients), custom webhook login, logout, and
auth state observation.
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
@@ -28,11 +34,27 @@ 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;
@@ -43,6 +65,8 @@ The device ID is auto-generated on first call and persisted in localStorage
```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 }
```
@@ -50,6 +74,36 @@ On success both tokens are saved to the client's `TokenStore`, the runtime
starts (domains warmed, scenario engine restored, `player_login` event fired),
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