@voltro/plugin-auth-social 0.85.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,10 +1,18 @@
1
1
  import { AuthConfig } from '@voltro/plugin-auth';
2
+ import { DataStore } from '@voltro/database';
2
3
  import { Effect } from 'effect';
4
+ import { GuestAuthOptions } from '@voltro/plugin-auth';
5
+ import { GuestAuthService } from '@voltro/plugin-auth';
6
+ import { HotStoreShape } from '@voltro/kv/hot';
7
+ import { PluginEnvVar } from '@voltro/protocol';
8
+ import { PluginPermission } from '@voltro/protocol';
3
9
  import { Predicate } from '@voltro/database';
4
10
  import { Subject } from '@voltro/protocol';
5
11
  import { TableLike } from '@voltro/database';
6
12
  import { UserStore } from '@voltro/plugin-auth';
13
+ import { VoidIfEmpty } from 'effect/Types';
7
14
  import { VoltroPlugin } from '@voltro/protocol';
15
+ import { YieldableError } from 'effect/Cause';
8
16
 
9
17
  /** Default lifetime we mint. Minutes, not months — see the header. */
10
18
  export declare const APPLE_CLIENT_SECRET_DEFAULT_TTL_S = 900;
@@ -48,6 +56,13 @@ export declare interface AppleUserPayload {
48
56
  readonly email: string | null;
49
57
  }
50
58
 
59
+ /** Preserve the guest subject ID. Conflict with any existing local email or
60
+ * provider link refuses with merge-required; this function never merges or
61
+ * moves another account automatically. A provider account without an address
62
+ * (Steam, Epic, a console) registers the guest without one, never a synthetic
63
+ * address. */
64
+ export declare const completeGuestSocialUpgrade: (options: GuestSocialUpgradeOptions) => Effect.Effect<GuestSocialUpgradeResult>;
65
+
51
66
  /**
52
67
  * Resolve a verified social profile into a session, applying the account-link
53
68
  * policy and the subject guards.
@@ -61,7 +76,7 @@ export declare const completeSocialSignIn: (o: SocialSignInOptions) => Effect.Ef
61
76
 
62
77
  /** DataStore-backed store — the production choice. Bind it from the plugin's
63
78
  * `bindDataStore` hook, or construct it yourself over `ctx.store`. */
64
- export declare const dataStoreSocialIdentityStore: (store: SocialIdentityDataStore) => SocialIdentityStore;
79
+ export declare const dataStoreSocialIdentityStore: (store: SocialIdentityDataStore | Pick<DataStore, "query" | "insert" | "update" | "delete"> | Pick<DataStore, "query" | "insert" | "insertIgnoreWithOutcome" | "update" | "delete">) => SocialIdentityStore;
65
80
 
66
81
  /**
67
82
  * Decide what a verified social identity means for local accounts.
@@ -71,6 +86,68 @@ export declare const dataStoreSocialIdentityStore: (store: SocialIdentityDataSto
71
86
  */
72
87
  export declare const decideSocialLink: (input: SocialLinkInput) => SocialLinkDecision;
73
88
 
89
+ /**
90
+ * A platform login for a platform Voltro does not ship: a console or store
91
+ * whose SDK issues a ticket your server can verify (often under NDA). `verify`
92
+ * receives the ticket exactly as the game sent it and returns the platform's
93
+ * stable account id, or throws {@link PlatformTicketError} when the platform
94
+ * refuses it.
95
+ */
96
+ export declare const definePlatformLogin: (definition: PlatformLoginDefinition) => PlatformLogin;
97
+
98
+ /** The authenticated Discord user, without an access token or arbitrary API
99
+ * payload. Discord snowflakes remain strings; number coercion loses bits. */
100
+ export declare interface DiscordIdentity {
101
+ readonly accountId: string;
102
+ readonly login: string;
103
+ readonly name: string | null;
104
+ readonly avatarUrl: string | null;
105
+ readonly email: string | null;
106
+ readonly emailVerified: boolean;
107
+ }
108
+
109
+ /**
110
+ * Epic Online Services Connect: the game calls `EOS_Connect_CopyIdToken` after
111
+ * `EOS_Connect_Login` and sends the token; the server checks Epic's signature,
112
+ * issuer, client and deployment. The account id is the Product User ID, the one
113
+ * EOS keeps for a player across every account linked to it (Epic, Steam,
114
+ * consoles), so this login covers every platform EOS covers.
115
+ */
116
+ export declare const eosPlatformLogin: (options?: EosPlatformLoginOptions) => PlatformLogin;
117
+
118
+ export declare interface EosPlatformLoginOptions {
119
+ /** EOS client id the game initializes the SDK with. Default: `VOLTRO_EOS_CLIENT_ID`. */
120
+ readonly clientId?: string;
121
+ /** EOS deployment id; tokens from any other deployment are refused. Default: `VOLTRO_EOS_DEPLOYMENT_ID`. */
122
+ readonly deploymentId?: string;
123
+ /** Test seam — a loopback JWKS. */
124
+ readonly jwksUrl?: string;
125
+ }
126
+
127
+ export declare interface EpicIdentity {
128
+ readonly accountId: string;
129
+ readonly login: string;
130
+ readonly name: null;
131
+ readonly avatarUrl: null;
132
+ readonly email: null;
133
+ readonly emailVerified: false;
134
+ }
135
+
136
+ export declare const fetchDiscordIdentity: (accessToken: string, options: {
137
+ readonly apiBase: string;
138
+ readonly fetchImpl?: typeof fetch;
139
+ }) => Promise<DiscordIdentity>;
140
+
141
+ /** Authenticate through Epic's documented v2 token introspection endpoint.
142
+ * Account ids are read only from the server response, never a client payload
143
+ * or an unverified access-token body. No provider email proof is available. */
144
+ export declare const fetchEpicIdentity: (accessToken: string, options: {
145
+ readonly apiBase: string;
146
+ readonly clientId: string;
147
+ readonly fetchImpl?: typeof fetch;
148
+ readonly now?: () => number;
149
+ }) => Promise<EpicIdentity>;
150
+
74
151
  /**
75
152
  * Resolve the authenticated GitHub user behind an access token.
76
153
  *
@@ -95,6 +172,25 @@ export declare interface GithubIdentity {
95
172
  readonly emailVerified: boolean;
96
173
  }
97
174
 
175
+ export declare interface GuestSocialUpgradeOptions {
176
+ /** Verified server-side provider result, never a client-submitted profile. */
177
+ readonly profile: SocialProfile;
178
+ readonly credential: string;
179
+ readonly store: DataStore;
180
+ readonly guest: GuestAuthOptions;
181
+ /** The same complete lifecycle port installed by the guest plugin. */
182
+ readonly service?: GuestAuthService;
183
+ readonly users: UserStore;
184
+ readonly config: AuthConfig;
185
+ /** Required when ensureActor is installed: bind its write to this same
186
+ * transaction. There must be no independent pool/write during promotion. */
187
+ readonly configForTransaction?: (store: DataStore) => AuthConfig;
188
+ readonly ipAddress?: string | null;
189
+ readonly userAgent?: string | null;
190
+ }
191
+
192
+ declare type GuestSocialUpgradeResult = SocialSignInOk | SocialSignInRefused;
193
+
98
194
  /** Is this one of Apple's per-app relay addresses? Used as a fallback when the
99
195
  * `is_private_email` claim is absent (older tokens omit it). */
100
196
  export declare const isApplePrivateRelayEmail: (email: string | null) => boolean;
@@ -121,6 +217,12 @@ export declare const linkSocialIdentity: (store: SocialIdentityStore, userId: st
121
217
  * this table means every user's social login unlinks. Not for production. */
122
218
  export declare const memorySocialIdentityStore: (seed?: ReadonlyArray<SocialIdentityRecord>) => SocialIdentityStore;
123
219
 
220
+ declare interface NativeGuestUpgradeConfig {
221
+ /** Exact redirect URIs the app may name — a custom scheme (`acme://auth/upgrade`) or an
222
+ * https universal link. No wildcards. */
223
+ readonly redirectUris: ReadonlyArray<string>;
224
+ }
225
+
124
226
  /**
125
227
  * Parse Apple's `user` form field. Returns `null` for an absent or unparseable
126
228
  * value — which is the NORMAL case on every authorization after the first, not
@@ -129,6 +231,42 @@ export declare const memorySocialIdentityStore: (seed?: ReadonlyArray<SocialIden
129
231
  */
130
232
  export declare const parseAppleUserPayload: (raw: string | undefined | null) => AppleUserPayload | null;
131
233
 
234
+ /** The platform account a verified ticket proves. */
235
+ export declare interface PlatformAccount {
236
+ /** The platform's stable account id: a SteamID64, an EOS Product User ID, a
237
+ * console account id. This, never a name, is what the identity row is keyed by. */
238
+ readonly accountId: string;
239
+ }
240
+
241
+ /** One platform a game can sign in with. Build one with {@link steamPlatformLogin},
242
+ * {@link eosPlatformLogin} or {@link definePlatformLogin}. */
243
+ export declare interface PlatformLogin {
244
+ /** Route segment and identity namespace: `steam`, `eos`, `xbox`, … */
245
+ readonly id: string;
246
+ /** Verify a ticket with the platform. Throws {@link PlatformTicketError} for a
247
+ * ticket the platform refuses; any other failure answers 503. */
248
+ readonly verify: (ticket: string) => Promise<PlatformAccount>;
249
+ readonly declaredEnv: ReadonlyArray<PluginEnvVar>;
250
+ readonly permissions: ReadonlyArray<PluginPermission>;
251
+ /** Resolve every credential once; throws when one is missing. Runs at boot. */
252
+ readonly check: () => void;
253
+ }
254
+
255
+ export declare interface PlatformLoginDefinition {
256
+ readonly id: string;
257
+ readonly verify: (ticket: string) => Promise<PlatformAccount>;
258
+ readonly declaredEnv?: ReadonlyArray<PluginEnvVar>;
259
+ readonly permissions?: ReadonlyArray<PluginPermission>;
260
+ readonly check?: () => void;
261
+ }
262
+
263
+ /** The platform refused a game client's sign-in ticket. One class for every
264
+ * reason, for the same reason as {@link SocialIdTokenError}: the caller must
265
+ * refuse the sign-in either way, and the `message` says which check failed. */
266
+ export declare class PlatformTicketError extends SocialAuthError {
267
+ constructor(message: string);
268
+ }
269
+
132
270
  /** Test seam — drop the parsed-key and minted-secret caches. */
133
271
  export declare const _resetAppleSecretCache: () => void;
134
272
 
@@ -183,8 +321,6 @@ export declare type SocialAuthErrorCode =
183
321
  | 'id_token_invalid'
184
322
  /** The ID token verified but its `nonce` was not the one we minted. */
185
323
  | 'nonce_mismatch'
186
- /** The provider identified the user but gave us no email to work with. */
187
- | 'no_email'
188
324
  /** An account with this email exists and the link policy refused to attach. */
189
325
  | 'account_exists_unlinked'
190
326
  /** Linking requires a provider-VERIFIED email and this one is not. */
@@ -192,14 +328,24 @@ export declare type SocialAuthErrorCode =
192
328
  /** Linking refused because the address is a per-app Apple private relay. */
193
329
  | 'private_relay_email'
194
330
  /** A post-authentication subject guard vetoed the login. */
195
- | 'guard_rejected';
331
+ | 'guard_rejected'
332
+ /** The platform refused a game client's sign-in ticket (forged, expired,
333
+ * another app or deployment). */
334
+ | 'ticket_rejected';
196
335
 
197
336
  export declare const socialAuthPlugin: (options: SocialAuthPluginOptions) => VoltroPlugin;
198
337
 
199
338
  export declare interface SocialAuthPluginOptions {
200
339
  /** Which providers this app offers. A key with an empty object takes every
201
340
  * credential from the environment. */
202
- readonly providers: Partial<Record<SocialProviderId, SocialProviderConfig>>;
341
+ readonly providers?: Partial<Record<SocialProviderId, SocialProviderConfig>>;
342
+ /**
343
+ * Platforms a game client signs in with by ticket: `steamPlatformLogin()`,
344
+ * `eosPlatformLogin()`, or your own `definePlatformLogin(...)` for a console.
345
+ * Mounts `POST {prefix}/platform/{id}/sign-in`, and with `guestUpgrade` also
346
+ * `POST {prefix}/platform/{id}/link`. A platform account needs no email.
347
+ */
348
+ readonly platforms?: ReadonlyArray<PlatformLogin>;
203
349
  /** The same user store `authRoutesPlugin` runs on. */
204
350
  readonly users: UserStore;
205
351
  /**
@@ -238,6 +384,9 @@ export declare interface SocialAuthPluginOptions {
238
384
  readonly stateCookieName?: string;
239
385
  /** Disambiguates multiple instances of this plugin in one app. */
240
386
  readonly name?: string;
387
+ /** Opt-in two-step browser promotion. Provider login only prepares a signed
388
+ * handoff; a CSRF-protected confirmation must prove the durable guest device. */
389
+ readonly guestUpgrade?: SocialGuestUpgradeConfig;
241
390
  }
242
391
 
243
392
  /** The tables this package contributes, as an array. */
@@ -320,7 +469,7 @@ export declare const socialCompleteLogin: (o: SocialCompleteLoginOptions) => Pro
320
469
  export declare interface SocialCompleteLoginOptions {
321
470
  readonly provider: SocialProviderId;
322
471
  readonly clientId: string;
323
- /** Google / GitHub: the OAuth client secret. Apple: omit and pass
472
+ /** OAuth client secret. Apple: omit and pass
324
473
  * {@link SocialCompleteLoginOptions.appleKey} — its secret is a JWT we sign. */
325
474
  readonly clientSecret?: string;
326
475
  /** Apple only: the `.p8` key material a client secret is minted from. */
@@ -336,8 +485,8 @@ export declare interface SocialCompleteLoginOptions {
336
485
  readonly expectedState: string;
337
486
  /** The PKCE verifier `socialBeginLogin` minted. */
338
487
  readonly codeVerifier: string;
339
- /** The OIDC nonce `socialBeginLogin` minted. Required for Google and Apple;
340
- * meaningless for GitHub, which returns no ID token. */
488
+ /** The OIDC nonce `socialBeginLogin` minted. Required for every OIDC
489
+ * provider; meaningless for providers that return no ID token. */
341
490
  readonly expectedNonce?: string;
342
491
  /** Apple only: the raw `user` form field. Present on the FIRST authorization
343
492
  * and never again — see `apple.ts`. */
@@ -376,6 +525,18 @@ export declare class SocialExchangeError extends SocialAuthError {
376
525
  constructor(code: SocialAuthErrorCode, message: string, status?: number);
377
526
  }
378
527
 
528
+ export declare interface SocialGuestUpgradeConfig {
529
+ readonly guest: GuestAuthOptions;
530
+ /** Reuse the port installed by auth.guest; no automatic backend switch. */
531
+ readonly service?: (store: DataStore) => GuestAuthService;
532
+ /** Same-origin application page presenting explicit upgrade confirmation. */
533
+ readonly confirmationRedirect: string;
534
+ readonly configForTransaction?: (store: DataStore) => AuthConfig;
535
+ /** Opt-in promotion for cookie-less game clients through the system browser and a sealed,
536
+ * PKCE-bound one-time code. Absent mounts no `/upgrade/native/*` route. */
537
+ readonly native?: NativeGuestUpgradeConfig;
538
+ }
539
+
379
540
  /**
380
541
  * The social-identity table.
381
542
  *
@@ -386,6 +547,17 @@ export declare class SocialExchangeError extends SocialAuthError {
386
547
  */
387
548
  export declare const socialIdentitiesTable: TableLike;
388
549
 
550
+ /** The provider account already has an identity row: another login created it
551
+ * first (two first sign-ins of one Steam player racing). Read it and use it. */
552
+ export declare class SocialIdentityConflict extends SocialIdentityConflict_base<{
553
+ readonly provider: string;
554
+ }> {
555
+ }
556
+
557
+ declare const SocialIdentityConflict_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
558
+ readonly _tag: "SocialIdentityConflict";
559
+ } & Readonly<A>;
560
+
389
561
  /** The slice of `DataStore` this store needs — narrow so a caller can pass a
390
562
  * transactional view, a namespaced view, or a test double. */
391
563
  export declare interface SocialIdentityDataStore {
@@ -399,6 +571,14 @@ export declare interface SocialIdentityDataStore {
399
571
  }>;
400
572
  }): Promise<ReadonlyArray<Readonly<Record<string, unknown>>>>;
401
573
  insert(table: string, row: Readonly<Record<string, unknown>>): Promise<Readonly<Record<string, unknown>>>;
574
+ /** When present, the identity is recorded with it: the store decides atomically
575
+ * which of two concurrent first logins won, also where it enforces no unique. */
576
+ insertIgnoreWithOutcome?(table: string, row: Readonly<Record<string, unknown>>, options: {
577
+ readonly conflictColumns: ReadonlyArray<string>;
578
+ }): Promise<{
579
+ readonly row: Readonly<Record<string, unknown>>;
580
+ readonly outcome: 'inserted' | 'ignored';
581
+ }>;
402
582
  update(table: string, primaryKey: string, patch: Readonly<Record<string, unknown>>): Promise<Readonly<Record<string, unknown>> | null>;
403
583
  delete(table: string, primaryKey: string): Promise<boolean>;
404
584
  }
@@ -412,6 +592,11 @@ export declare interface SocialIdentityInput {
412
592
  readonly emailVerified: boolean;
413
593
  }
414
594
 
595
+ /** Verified browser and native identities share the same account-link contract.
596
+ * Steam uses OpenID/tickets rather than an OAuth authorize-code descriptor; EOS
597
+ * is a platform login (`eosPlatformLogin`), keyed by the Product User ID. */
598
+ export declare type SocialIdentityProviderId = SocialProviderId | 'steam' | 'eos';
599
+
415
600
  export declare interface SocialIdentityRecord {
416
601
  readonly id: string;
417
602
  readonly userId: string;
@@ -432,8 +617,9 @@ export declare interface SocialIdentityStore {
432
617
  readonly findByProviderAccount: (provider: string, providerAccountId: string) => Effect.Effect<SocialIdentityRecord | null>;
433
618
  /** Every provider a user has connected — the account-settings list. */
434
619
  readonly listForUser: (userId: string) => Effect.Effect<ReadonlyArray<SocialIdentityRecord>>;
435
- /** Create the link. */
436
- readonly insert: (input: SocialIdentityInput) => Effect.Effect<SocialIdentityRecord>;
620
+ /** Create the link. Fails with {@link SocialIdentityConflict} when the provider
621
+ * account already has one — the unique `[provider, providerAccountId]`. */
622
+ readonly insert: (input: SocialIdentityInput) => Effect.Effect<SocialIdentityRecord, SocialIdentityConflict>;
437
623
  /** Stamp `lastLoginAt` on a returning login. */
438
624
  readonly touch: (identityId: string, at: Date) => Effect.Effect<void>;
439
625
  /** Unlink a provider from a user. Returns whether a row was removed. */
@@ -459,7 +645,8 @@ export declare type SocialLinkDecision =
459
645
  readonly kind: 'sign-in';
460
646
  readonly userId: string;
461
647
  }
462
- /** No identity, no account with this email — provision a new user. */
648
+ /** No identity, and no account with this email (or no email at all) —
649
+ * provision a new user. */
463
650
  | {
464
651
  readonly kind: 'create-user';
465
652
  }
@@ -520,14 +707,15 @@ export declare interface SocialLoginHandoff {
520
707
  }
521
708
 
522
709
  /**
523
- * A verified identity, normalised across the three providers.
710
+ * A verified identity, normalised across the registered providers.
524
711
  *
525
712
  * `emailVerified` is the field every security decision downstream reads. It is
526
713
  * the PROVIDER's assertion that it verified ownership of `email` — never our
527
714
  * inference, and never `true` by default. See `linking.ts`.
528
715
  */
529
716
  export declare interface SocialProfile {
530
- readonly provider: SocialProviderId;
717
+ /** A registered provider id, or the id of a platform login (`eos`, a console). */
718
+ readonly provider: SocialIdentityProviderId | (string & {});
531
719
  /** The provider's stable, opaque id for this account — `sub` on Google and
532
720
  * Apple, the numeric account id on GitHub. This, not the email, is what an
533
721
  * identity row is keyed by: an email can change hands, this cannot. */
@@ -562,7 +750,7 @@ export declare const socialProvider: (id: string, overrides?: SocialEndpointOver
562
750
  * value, because a default credential is a shipped secret. */
563
751
  export declare interface SocialProviderConfig {
564
752
  readonly clientId?: string;
565
- /** Google / GitHub. Apple has none — it uses {@link SocialProviderConfig.appleKey}. */
753
+ /** OAuth client secret. Apple uses {@link SocialProviderConfig.appleKey}. */
566
754
  readonly clientSecret?: string;
567
755
  /** Apple only: Team ID + Key ID + the `.p8` contents. */
568
756
  readonly appleKey?: AppleClientSecretKey;
@@ -599,10 +787,10 @@ export declare interface SocialProviderDescriptor {
599
787
  }
600
788
 
601
789
  /** The providers this package ships. */
602
- export declare type SocialProviderId = 'google' | 'github' | 'apple';
790
+ export declare type SocialProviderId = 'google' | 'github' | 'apple' | 'discord' | 'twitch' | 'microsoft' | 'epic';
603
791
 
604
792
  /** How the provider hands the callback back to us. Apple POSTs (cross-site,
605
- * `form_post`) whenever `name` / `email` scopes are requested; the other two
793
+ * `form_post`) whenever `name` / `email` scopes are requested; the others
606
794
  * redirect with a query string. This changes the cookie the state must live
607
795
  * in — see `plugin.ts`. */
608
796
  export declare type SocialResponseMode = 'query' | 'form_post';
@@ -614,6 +802,12 @@ export declare interface SocialSignInOk {
614
802
  readonly subject: Subject;
615
803
  /** Attach this to the response. */
616
804
  readonly setCookie: string;
805
+ /** The same session for a client that presents it in the session header
806
+ * instead of a cookie (a game). `expiresAt` is in Unix seconds. */
807
+ readonly session: {
808
+ readonly value: string;
809
+ readonly expiresAt: number;
810
+ };
617
811
  /** A new local user was provisioned by this login. */
618
812
  readonly created: boolean;
619
813
  /** The identity was attached to a PRE-EXISTING account by policy. */
@@ -663,4 +857,86 @@ export declare class SocialStateMismatchError extends SocialAuthError {
663
857
  constructor(message: string);
664
858
  }
665
859
 
860
+ /** Steam OpenID 2.0 does not use OAuth PKCE. State is server minted and bound
861
+ * into the exact return_to which Steam signs. Persist this handoff securely. */
862
+ export declare const steamBeginOpenId: (options: {
863
+ readonly returnTo: string;
864
+ readonly realm?: string;
865
+ }) => SteamOpenIdHandoff;
866
+
867
+ /** Direct OP verification plus local atomic replay admission. Unavailable hot
868
+ * state refuses; memory ports are explicitly refused for a multi-node owner. */
869
+ export declare const steamCompleteOpenId: (options: SteamCompleteOpenIdOptions) => Effect.Effect<SocialProfile, SocialAuthError>;
870
+
871
+ export declare interface SteamCompleteOpenIdOptions {
872
+ /** Actual browser callback URL, not a client-supplied asserted return URL. */
873
+ readonly callbackUrl: string;
874
+ readonly expectedReturnTo: string;
875
+ readonly expectedState: string;
876
+ /** Inject the registry-backed HotStore; there is no private Redis client. */
877
+ readonly hotStore: HotStoreShape;
878
+ readonly namespace: string;
879
+ readonly multiNode?: boolean;
880
+ readonly maxNonceAgeMs?: number;
881
+ readonly clockSkewMs?: number;
882
+ readonly now?: () => number;
883
+ readonly fetchImpl?: typeof fetch;
884
+ /** How long Steam may take to answer. Default 5000 ms. */
885
+ readonly timeoutMs?: number;
886
+ /** Loopback fixture only; the asserted OP remains pinned to Steam. */
887
+ readonly verificationUrl?: string;
888
+ }
889
+
890
+ export declare interface SteamOpenIdHandoff {
891
+ readonly url: string;
892
+ readonly state: string;
893
+ readonly returnTo: string;
894
+ readonly realm: string;
895
+ }
896
+
897
+ /**
898
+ * Steam: the game calls `ISteamUser::GetAuthTicketForWebApi(identity)` and sends
899
+ * the ticket as hex; the server asks Steam's partner API who it belongs to. The
900
+ * account id is the player's SteamID64 — also for a family-shared copy, whose
901
+ * owner is a different account.
902
+ */
903
+ export declare const steamPlatformLogin: (options?: SteamPlatformLoginOptions) => PlatformLogin;
904
+
905
+ export declare interface SteamPlatformLoginOptions {
906
+ /** Steam App ID. Default: `VOLTRO_STEAM_APP_ID`. */
907
+ readonly appId?: number;
908
+ /** The identity string the game passes to `GetAuthTicketForWebApi`. Default `voltro`. */
909
+ readonly identity?: string;
910
+ /** Steamworks Web API publisher key. Default: `VOLTRO_STEAM_PUBLISHER_KEY`. Never ships to clients. */
911
+ readonly publisherKey?: string;
912
+ /** How long Steam may take to answer before the sign-in answers 502. Default 5000 ms. */
913
+ readonly timeoutMs?: number;
914
+ /** Sign in players the publisher banned from this app. Default false: they are refused with 403. */
915
+ readonly allowPublisherBanned?: boolean;
916
+ /** Test seam — a loopback stand-in for the partner API. */
917
+ readonly verificationUrl?: string;
918
+ readonly fetchImpl?: typeof fetch;
919
+ }
920
+
921
+ export declare interface SteamWebApiTicketOptions {
922
+ readonly ticket: string;
923
+ readonly appId: number;
924
+ readonly identity: string;
925
+ readonly publisherKey: string;
926
+ readonly fetchImpl?: typeof fetch;
927
+ /** How long Steam may take to answer. Default 5000 ms. */
928
+ readonly timeoutMs?: number;
929
+ /** Accept a player the publisher banned from this app. Default false. */
930
+ readonly allowPublisherBanned?: boolean;
931
+ /** Loopback fixture only. The production verifier is the publisher API. */
932
+ readonly verificationUrl?: string;
933
+ }
934
+
935
+ /** Run a platform verifier and sort its failure into refused (401) or unavailable (503). */
936
+ export declare const verifyPlatformTicket: (platform: PlatformLogin, ticket: string) => Promise<PlatformAccount>;
937
+
938
+ /** Steamworks GetAuthTicketForWebApi hex tickets, verified on the secure
939
+ * server against the configured app and identity. No supplied SteamID wins. */
940
+ export declare const verifySteamWebApiTicket: (options: SteamWebApiTicketOptions) => Promise<SocialProfile>;
941
+
666
942
  export { }