@absolutejs/auth 0.69.6 → 0.71.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.
@@ -248,6 +248,30 @@ var createMobileAuthClient = (config) => {
248
248
  let stopResume;
249
249
  let startPromise;
250
250
  const pendingSignIns = new Map;
251
+ let currentPrincipal;
252
+ const principalListeners = new Set;
253
+ const publishPrincipal = (principal2) => {
254
+ if (currentPrincipal !== undefined && currentPrincipal?.namespace === principal2?.namespace)
255
+ return;
256
+ currentPrincipal = principal2;
257
+ for (const listener of principalListeners)
258
+ listener(principal2);
259
+ };
260
+ const principalFor = async (user) => {
261
+ const partition = typeof user.absolutejs_sync_partition === "string" && user.absolutejs_sync_partition.length > 0 ? user.absolutejs_sync_partition : undefined;
262
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify([
263
+ issuer,
264
+ config.clientId,
265
+ user.sub,
266
+ partition ?? null
267
+ ])));
268
+ return {
269
+ issuer,
270
+ namespace: `auth:v1:${base64Url(new Uint8Array(digest))}`,
271
+ ...partition === undefined ? {} : { partition },
272
+ subject: user.sub
273
+ };
274
+ };
251
275
  const fetchDiscovery = async () => {
252
276
  const url = new URL("/.well-known/openid-configuration", `${issuer}/`);
253
277
  const response = await fetchImpl(url, {
@@ -323,18 +347,21 @@ var createMobileAuthClient = (config) => {
323
347
  };
324
348
  const rotateAccessToken = async () => {
325
349
  await assertSecureStorage();
326
- const refreshToken = await config.storage.get(REFRESH_KEY);
327
- if (!refreshToken)
328
- throw new MobileAuthError("token", "This app has no renewable mobile session.");
329
- const metadata = await discovery();
330
- const body = new URLSearchParams({
331
- client_id: config.clientId,
332
- grant_type: "refresh_token",
333
- refresh_token: refreshToken
334
- });
335
- body.set("resource", resource);
336
- const tokens = await tokenRequest(metadata, body);
337
- return (await acceptTokens(tokens)).accessToken;
350
+ const exchange = async () => {
351
+ const refreshToken = await config.storage.get(REFRESH_KEY);
352
+ if (!refreshToken)
353
+ throw new MobileAuthError("token", "This app has no renewable mobile session.");
354
+ const metadata = await discovery();
355
+ const body = new URLSearchParams({
356
+ client_id: config.clientId,
357
+ grant_type: "refresh_token",
358
+ refresh_token: refreshToken
359
+ });
360
+ body.set("resource", resource);
361
+ const tokens = await tokenRequest(metadata, body);
362
+ return (await acceptTokens(tokens)).accessToken;
363
+ };
364
+ return config.storage.withLock ? config.storage.withLock(REFRESH_KEY, exchange) : exchange();
338
365
  };
339
366
  const refreshAccessToken = async () => {
340
367
  if (access && access.expiresAt - clockSkewMs > now())
@@ -484,22 +511,31 @@ var createMobileAuthClient = (config) => {
484
511
  return authenticatedFetch(request);
485
512
  return fetchImpl(new Request(request, { credentials: "omit" }));
486
513
  };
514
+ const signedOut = () => {
515
+ publishPrincipal(null);
516
+ return null;
517
+ };
487
518
  const status = async () => {
488
519
  try {
489
520
  const metadata = await discovery();
490
521
  const response = await authenticatedFetch(metadata.userinfo_endpoint);
491
522
  if (response.status === 401)
492
- return null;
523
+ return signedOut();
493
524
  if (!response.ok)
494
525
  throw new MobileAuthError("network", `User info failed with HTTP ${response.status}.`);
495
526
  const user = await response.json();
496
527
  if (!isRecord(user) || typeof user.sub !== "string")
497
528
  throw new MobileAuthError("token", "The user-info response is malformed.");
498
- return { ...user, sub: user.sub };
529
+ const normalized = {
530
+ ...user,
531
+ sub: user.sub
532
+ };
533
+ publishPrincipal(await principalFor(normalized));
534
+ return normalized;
499
535
  } catch (error) {
500
- if (error instanceof MobileAuthError && (error.code === "oauth" || error.code === "token"))
501
- return null;
502
- throw error;
536
+ if (!(error instanceof MobileAuthError && (error.code === "oauth" || error.code === "token")))
537
+ throw error;
538
+ return signedOut();
503
539
  }
504
540
  };
505
541
  const socketTicket = async (audience = resource) => {
@@ -543,8 +579,21 @@ var createMobileAuthClient = (config) => {
543
579
  config.storage.remove(PENDING_KEY),
544
580
  config.storage.remove(REFRESH_KEY)
545
581
  ]);
582
+ publishPrincipal(null);
546
583
  }
547
584
  };
585
+ const principal = async () => {
586
+ await status();
587
+ return currentPrincipal ?? null;
588
+ };
589
+ const onPrincipalChange = (listener) => {
590
+ principalListeners.add(listener);
591
+ if (currentPrincipal !== undefined)
592
+ listener(currentPrincipal);
593
+ return () => {
594
+ principalListeners.delete(listener);
595
+ };
596
+ };
548
597
  const stop = async () => {
549
598
  await Promise.all([stopLinks?.(), stopResume?.()]);
550
599
  stopLinks = undefined;
@@ -555,6 +604,8 @@ var createMobileAuthClient = (config) => {
555
604
  fetch: authenticatedFetch,
556
605
  fetchOptional: optionalAuthenticatedFetch,
557
606
  handleCallback,
607
+ onPrincipalChange,
608
+ principal,
558
609
  refresh: refreshAccessToken,
559
610
  signIn,
560
611
  signOut,
@@ -600,5 +651,5 @@ export {
600
651
  MobileAuthError
601
652
  };
602
653
 
603
- //# debugId=E6C9C1D1A29260E464756E2164756E21
654
+ //# debugId=949AEA9AEBBABE7C64756E2164756E21
604
655
  //# sourceMappingURL=mobile.js.map
@@ -3,9 +3,9 @@
3
3
  "sources": ["../src/client/runtimeTransport.ts", "../src/client/mobile.ts"],
4
4
  "sourcesContent": [
5
5
  "import type { AuthClientTransport } from './createAuthClient';\n\ntype AuthTransportInstallation = { transport: AuthClientTransport };\ntype AuthTransportRegistry = { installations: AuthTransportInstallation[] };\n\nconst AUTH_TRANSPORT_REGISTRY = Symbol.for(\n\t'@absolutejs/auth/client-runtime-transport'\n);\nconst isRegistry = (value: unknown): value is AuthTransportRegistry =>\n\ttypeof value === 'object' &&\n\tvalue !== null &&\n\tArray.isArray(Reflect.get(value, 'installations'));\n\nconst createRegistry = () => {\n\tconst existing = Reflect.get(globalThis, AUTH_TRANSPORT_REGISTRY);\n\tif (isRegistry(existing)) return existing;\n\tconst created: AuthTransportRegistry = { installations: [] };\n\tObject.defineProperty(globalThis, AUTH_TRANSPORT_REGISTRY, {\n\t\tconfigurable: false,\n\t\tenumerable: false,\n\t\tvalue: created,\n\t\twritable: false\n\t});\n\n\treturn created;\n};\n\nconst registry = createRegistry();\n\nexport const getAuthClientRuntimeTransport = () =>\n\tregistry.installations.at(-1)?.transport;\n\nexport const installAuthClientRuntimeTransport = (\n\ttransport: AuthClientTransport\n) => {\n\tconst installation: AuthTransportInstallation = { transport };\n\tregistry.installations.push(installation);\n\n\treturn () => {\n\t\tconst index = registry.installations.indexOf(installation);\n\t\tif (index >= 0) registry.installations.splice(index, 1);\n\t};\n};\n",
6
- "export type MobileAuthSecureStorage = {\n\tcapability?: () => Promise<{\n\t\tavailable: boolean;\n\t\tmessage?: string;\n\t}>;\n\tget(key: string): Promise<string | null>;\n\tremove(key: string): Promise<void>;\n\tset(key: string, value: string): Promise<void>;\n};\n\nexport type MobileAuthLinks = {\n\tgetLaunchUrl(): Promise<string | null>;\n\tonOpen(\n\t\tlistener: (url: string) => void\n\t): Promise<() => Promise<void> | void>;\n\topenExternal(url: string): Promise<void>;\n};\n\nexport type MobileAuthLifecycle = {\n\tonResume?(listener: () => void): Promise<() => Promise<void> | void>;\n};\n\nexport type MobileAuthDiscovery = {\n\tauthorization_endpoint: string;\n\tcode_challenge_methods_supported?: string[];\n\tissuer: string;\n\tjwks_uri: string;\n\trevocation_endpoint?: string;\n\tsocket_ticket_endpoint?: string;\n\ttoken_endpoint: string;\n\ttoken_endpoint_auth_methods_supported?: string[];\n\tuserinfo_endpoint: string;\n};\n\nexport type MobileAuthClientConfig = {\n\tallowedOrigins?: readonly string[];\n\tclientId: string;\n\tclockSkewMs?: number;\n\tfetch?: typeof globalThis.fetch;\n\tissuer: string;\n\tlifecycle?: MobileAuthLifecycle;\n\tlinks: MobileAuthLinks;\n\tnow?: () => number;\n\tredirectUri: string;\n\tresource?: string;\n\tscopes?: readonly string[];\n\tstorage: MobileAuthSecureStorage;\n};\n\nexport type MobileAuthSignInOptions = {\n\tauthorizationParameters?: Readonly<Record<string, string>>;\n\tsignal?: AbortSignal;\n};\n\nexport type MobileAuthTokens = {\n\taccessToken: string;\n\texpiresAt: number;\n\tidToken: string;\n\trefreshToken: string;\n\tscope: string[];\n\ttokenType: 'Bearer';\n};\n\nexport type MobileAuthUser = Record<string, unknown> & { sub: string };\n\nexport type MobileAuthErrorCode =\n\t| 'aborted'\n\t| 'callback'\n\t| 'discovery'\n\t| 'id-token'\n\t| 'network'\n\t| 'oauth'\n\t| 'origin'\n\t| 'secure-storage'\n\t| 'token';\n\nexport class MobileAuthError extends Error {\n\treadonly code: MobileAuthErrorCode;\n\treadonly cause?: unknown;\n\n\tconstructor(\n\t\tcode: MobileAuthErrorCode,\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown }\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'MobileAuthError';\n\t\tthis.code = code;\n\t\tthis.cause = options?.cause;\n\t}\n}\n\ntype PendingAuthorization = {\n\tcreatedAt: number;\n\tnonce: string;\n\tstate: string;\n\tverifier: string;\n};\n\ntype TokenResponse = {\n\taccess_token: string;\n\texpires_in: number;\n\tid_token: string;\n\trefresh_token: string;\n\tscope?: string;\n\ttoken_type: string;\n};\n\ntype DeferredSignIn = {\n\treject: (error: unknown) => void;\n\tresolve: (tokens: MobileAuthTokens) => void;\n};\n\nconst PENDING_KEY = 'oidc.pending';\nconst REFRESH_KEY = 'oidc.refresh';\nconst DEFAULT_CLOCK_SKEW_MS = 30_000;\nconst PENDING_TTL_MS = 10 * 60_000;\nconst RANDOM_BYTES = 32;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n\ttypeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst base64Url = (value: Uint8Array) => {\n\tlet binary = '';\n\tfor (const byte of value) binary += String.fromCharCode(byte);\n\n\treturn btoa(binary)\n\t\t.replaceAll('+', '-')\n\t\t.replaceAll('/', '_')\n\t\t.replace(/=+$/u, '');\n};\n\nconst decodeBase64Url = (value: string) => {\n\tconst normalized = value.replaceAll('-', '+').replaceAll('_', '/');\n\tconst padded = normalized.padEnd(\n\t\tnormalized.length + ((4 - (normalized.length % 4)) % 4),\n\t\t'='\n\t);\n\tconst binary = atob(padded);\n\n\treturn Uint8Array.from(binary, (character) => character.charCodeAt(0));\n};\n\nconst randomValue = () => {\n\tconst value = new Uint8Array(RANDOM_BYTES);\n\tcrypto.getRandomValues(value);\n\n\treturn base64Url(value);\n};\n\nconst pkceChallenge = async (verifier: string) =>\n\tbase64Url(\n\t\tnew Uint8Array(\n\t\t\tawait crypto.subtle.digest(\n\t\t\t\t'SHA-256',\n\t\t\t\tnew TextEncoder().encode(verifier)\n\t\t\t)\n\t\t)\n\t);\n\nconst normalizeIssuer = (value: string) => {\n\tconst issuer = new URL(value);\n\tconst loopback =\n\t\tissuer.protocol === 'http:' &&\n\t\t['127.0.0.1', '[::1]', 'localhost'].includes(issuer.hostname);\n\tif (issuer.protocol !== 'https:' && !loopback)\n\t\tthrow new TypeError('Mobile auth issuer must use HTTPS.');\n\tif (issuer.username || issuer.password || issuer.search || issuer.hash)\n\t\tthrow new TypeError(\n\t\t\t'Mobile auth issuer cannot contain credentials, query, or fragment.'\n\t\t);\n\tissuer.pathname = issuer.pathname.replace(/\\/$/u, '');\n\n\treturn issuer.href.replace(/\\/$/u, '');\n};\n\nconst exactRedirect = (actualValue: string, expectedValue: string) => {\n\tconst actual = new URL(actualValue);\n\tconst expected = new URL(expectedValue);\n\n\treturn (\n\t\tactual.protocol === expected.protocol &&\n\t\tactual.host === expected.host &&\n\t\tactual.pathname === expected.pathname &&\n\t\tactual.username === '' &&\n\t\tactual.password === ''\n\t);\n};\n\nconst parsePending = (value: string | null) => {\n\tif (value === null) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(value);\n\t\tif (\n\t\t\t!isRecord(parsed) ||\n\t\t\ttypeof parsed.createdAt !== 'number' ||\n\t\t\ttypeof parsed.nonce !== 'string' ||\n\t\t\ttypeof parsed.state !== 'string' ||\n\t\t\ttypeof parsed.verifier !== 'string'\n\t\t)\n\t\t\treturn undefined;\n\n\t\treturn {\n\t\t\tcreatedAt: parsed.createdAt,\n\t\t\tnonce: parsed.nonce,\n\t\t\tstate: parsed.state,\n\t\t\tverifier: parsed.verifier\n\t\t} satisfies PendingAuthorization;\n\t} catch {\n\t\treturn undefined;\n\t}\n};\n\nconst parseTokenResponse = (value: unknown) => {\n\tif (\n\t\t!isRecord(value) ||\n\t\ttypeof value.access_token !== 'string' ||\n\t\ttypeof value.expires_in !== 'number' ||\n\t\t!Number.isFinite(value.expires_in) ||\n\t\tvalue.expires_in <= 0 ||\n\t\ttypeof value.id_token !== 'string' ||\n\t\ttypeof value.refresh_token !== 'string' ||\n\t\ttypeof value.token_type !== 'string'\n\t)\n\t\tthrow new MobileAuthError('token', 'The token response is malformed.');\n\tif (value.token_type.toLowerCase() !== 'bearer')\n\t\tthrow new MobileAuthError(\n\t\t\t'token',\n\t\t\t`Unsupported mobile token type ${value.token_type}; DPoP is not enabled for this client.`\n\t\t);\n\n\treturn {\n\t\taccess_token: value.access_token,\n\t\texpires_in: value.expires_in,\n\t\tid_token: value.id_token,\n\t\trefresh_token: value.refresh_token,\n\t\tscope: typeof value.scope === 'string' ? value.scope : undefined,\n\t\ttoken_type: value.token_type\n\t} satisfies TokenResponse;\n};\n\nconst responseBody = async (response: Response) => {\n\tconst text = await response.text();\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn text;\n\t}\n};\n\nconst requireEndpoint = (value: unknown, name: string, issuer: string) => {\n\tif (typeof value !== 'string')\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t`OIDC discovery is missing ${name}.`\n\t\t);\n\tconst endpoint = new URL(value);\n\tif (endpoint.protocol !== 'https:' && new URL(issuer).protocol === 'https:')\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t`OIDC discovery ${name} must use HTTPS.`\n\t\t);\n\n\treturn endpoint.href;\n};\n\nconst parseDiscovery = (\n\tvalue: unknown,\n\tissuer: string\n): MobileAuthDiscovery => {\n\tif (!isRecord(value) || value.issuer !== issuer)\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t'OIDC discovery issuer does not match the configured issuer.'\n\t\t);\n\tconst methods = Array.isArray(value.code_challenge_methods_supported)\n\t\t? value.code_challenge_methods_supported.filter(\n\t\t\t\t(method): method is string => typeof method === 'string'\n\t\t\t)\n\t\t: undefined;\n\tif (!methods?.includes('S256'))\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t'OIDC provider does not advertise S256 PKCE.'\n\t\t);\n\tconst authMethods = Array.isArray(\n\t\tvalue.token_endpoint_auth_methods_supported\n\t)\n\t\t? value.token_endpoint_auth_methods_supported.filter(\n\t\t\t\t(method): method is string => typeof method === 'string'\n\t\t\t)\n\t\t: undefined;\n\tif (!authMethods?.includes('none'))\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t'OIDC provider does not accept public clients at the token endpoint.'\n\t\t);\n\n\treturn {\n\t\tauthorization_endpoint: requireEndpoint(\n\t\t\tvalue.authorization_endpoint,\n\t\t\t'authorization_endpoint',\n\t\t\tissuer\n\t\t),\n\t\tcode_challenge_methods_supported: methods,\n\t\tissuer,\n\t\tjwks_uri: requireEndpoint(value.jwks_uri, 'jwks_uri', issuer),\n\t\trevocation_endpoint:\n\t\t\ttypeof value.revocation_endpoint === 'string'\n\t\t\t\t? requireEndpoint(\n\t\t\t\t\t\tvalue.revocation_endpoint,\n\t\t\t\t\t\t'revocation_endpoint',\n\t\t\t\t\t\tissuer\n\t\t\t\t\t)\n\t\t\t\t: undefined,\n\t\tsocket_ticket_endpoint:\n\t\t\ttypeof value.socket_ticket_endpoint === 'string'\n\t\t\t\t? requireEndpoint(\n\t\t\t\t\t\tvalue.socket_ticket_endpoint,\n\t\t\t\t\t\t'socket_ticket_endpoint',\n\t\t\t\t\t\tissuer\n\t\t\t\t\t)\n\t\t\t\t: undefined,\n\t\ttoken_endpoint: requireEndpoint(\n\t\t\tvalue.token_endpoint,\n\t\t\t'token_endpoint',\n\t\t\tissuer\n\t\t),\n\t\ttoken_endpoint_auth_methods_supported: authMethods,\n\t\tuserinfo_endpoint: requireEndpoint(\n\t\t\tvalue.userinfo_endpoint,\n\t\t\t'userinfo_endpoint',\n\t\t\tissuer\n\t\t)\n\t};\n};\n\nconst verifyIdToken = async ({\n\tclientId,\n\tfetchImpl,\n\tidToken,\n\tissuer,\n\tjwksUri,\n\tnonce,\n\tnow\n}: {\n\tclientId: string;\n\tfetchImpl: typeof globalThis.fetch;\n\tidToken: string;\n\tissuer: string;\n\tjwksUri: string;\n\tnonce: string;\n\tnow: number;\n}) => {\n\tconst [encodedHeader, encodedPayload, encodedSignature, ...extra] =\n\t\tidToken.split('.');\n\tif (!encodedHeader || !encodedPayload || !encodedSignature || extra.length)\n\t\tthrow new MobileAuthError('id-token', 'The ID token is malformed.');\n\tlet header: unknown;\n\tlet payload: unknown;\n\ttry {\n\t\theader = JSON.parse(\n\t\t\tnew TextDecoder().decode(decodeBase64Url(encodedHeader))\n\t\t);\n\t\tpayload = JSON.parse(\n\t\t\tnew TextDecoder().decode(decodeBase64Url(encodedPayload))\n\t\t);\n\t} catch (cause) {\n\t\tthrow new MobileAuthError('id-token', 'The ID token is malformed.', {\n\t\t\tcause\n\t\t});\n\t}\n\tif (\n\t\t!isRecord(header) ||\n\t\theader.alg !== 'ES256' ||\n\t\ttypeof header.kid !== 'string' ||\n\t\t!isRecord(payload)\n\t)\n\t\tthrow new MobileAuthError(\n\t\t\t'id-token',\n\t\t\t'The ID token header or claims are invalid.'\n\t\t);\n\tconst response = await fetchImpl(jwksUri, { cache: 'no-store' });\n\tif (!response.ok)\n\t\tthrow new MobileAuthError(\n\t\t\t'network',\n\t\t\t'Unable to fetch OIDC signing keys.'\n\t\t);\n\tconst body: unknown = await response.json();\n\tconst keys = isRecord(body) && Array.isArray(body.keys) ? body.keys : [];\n\tconst jwk = keys.find(\n\t\t(candidate): candidate is JsonWebKey & { kid: string } =>\n\t\t\tisRecord(candidate) && candidate.kid === header.kid\n\t);\n\tif (!jwk)\n\t\tthrow new MobileAuthError(\n\t\t\t'id-token',\n\t\t\t'The ID token signing key is unknown.'\n\t\t);\n\tconst key = await crypto.subtle.importKey(\n\t\t'jwk',\n\t\tjwk,\n\t\t{ hash: 'SHA-256', name: 'ECDSA', namedCurve: 'P-256' },\n\t\tfalse,\n\t\t['verify']\n\t);\n\tconst valid = await crypto.subtle.verify(\n\t\t{ hash: 'SHA-256', name: 'ECDSA' },\n\t\tkey,\n\t\tdecodeBase64Url(encodedSignature),\n\t\tnew TextEncoder().encode(`${encodedHeader}.${encodedPayload}`)\n\t);\n\tconst audience = payload.aud;\n\tif (\n\t\t!valid ||\n\t\tpayload.iss !== issuer ||\n\t\t!(\n\t\t\taudience === clientId ||\n\t\t\t(Array.isArray(audience) && audience.includes(clientId))\n\t\t) ||\n\t\tpayload.nonce !== nonce ||\n\t\ttypeof payload.exp !== 'number' ||\n\t\tpayload.exp * 1000 <= now\n\t)\n\t\tthrow new MobileAuthError(\n\t\t\t'id-token',\n\t\t\t'The ID token signature or claims are invalid.'\n\t\t);\n};\n\nexport const createMobileAuthClient = (config: MobileAuthClientConfig) => {\n\tconst issuer = normalizeIssuer(config.issuer);\n\tconst redirectUri = new URL(config.redirectUri).href;\n\tconst fetchImpl = config.fetch ?? globalThis.fetch;\n\tconst now = config.now ?? Date.now;\n\tconst clockSkewMs = config.clockSkewMs ?? DEFAULT_CLOCK_SKEW_MS;\n\tconst scopes = [...new Set(config.scopes ?? ['openid', 'profile'])];\n\tconst resource = config.resource ?? issuer;\n\tif (!scopes.includes('openid')) scopes.unshift('openid');\n\tconst allowedOrigins = new Set(\n\t\t(config.allowedOrigins ?? [new URL(issuer).origin]).map(\n\t\t\t(value) => new URL(value).origin\n\t\t)\n\t);\n\tlet discoveryPromise: Promise<MobileAuthDiscovery> | undefined;\n\tlet access: Omit<MobileAuthTokens, 'refreshToken'> | undefined;\n\tlet refreshPromise: Promise<string> | undefined;\n\tlet stopLinks: (() => Promise<void> | void) | undefined;\n\tlet stopResume: (() => Promise<void> | void) | undefined;\n\tlet startPromise: Promise<void> | undefined;\n\tconst pendingSignIns = new Map<string, DeferredSignIn>();\n\n\tconst fetchDiscovery = async () => {\n\t\tconst url = new URL('/.well-known/openid-configuration', `${issuer}/`);\n\t\tconst response = await fetchImpl(url, {\n\t\t\tcache: 'no-store',\n\t\t\theaders: { accept: 'application/json' }\n\t\t});\n\t\tif (!response.ok)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'discovery',\n\t\t\t\t`OIDC discovery failed with HTTP ${response.status}.`\n\t\t\t);\n\n\t\treturn parseDiscovery(await response.json(), issuer);\n\t};\n\n\tconst discovery = () => {\n\t\tdiscoveryPromise ??= fetchDiscovery();\n\n\t\treturn discoveryPromise;\n\t};\n\n\tconst assertSecureStorage = async () => {\n\t\tconst capability = await config.storage.capability?.();\n\t\tif (capability && !capability.available)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'secure-storage',\n\t\t\t\tcapability.message ??\n\t\t\t\t\t'Native secure credential storage is unavailable.'\n\t\t\t);\n\t};\n\n\tconst tokenRequest = async (\n\t\tmetadata: MobileAuthDiscovery,\n\t\tbody: URLSearchParams,\n\t\tnonce?: string\n\t) => {\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetchImpl(metadata.token_endpoint, {\n\t\t\t\tbody,\n\t\t\t\tcredentials: 'omit',\n\t\t\t\theaders: {\n\t\t\t\t\taccept: 'application/json',\n\t\t\t\t\t'content-type': 'application/x-www-form-urlencoded'\n\t\t\t\t},\n\t\t\t\tmethod: 'POST'\n\t\t\t});\n\t\t} catch (cause) {\n\t\t\tthrow new MobileAuthError('network', 'The token request failed.', {\n\t\t\t\tcause\n\t\t\t});\n\t\t}\n\t\tconst value = await responseBody(response);\n\t\tif (!response.ok) {\n\t\t\tconst oauthCode =\n\t\t\t\tisRecord(value) && typeof value.error === 'string'\n\t\t\t\t\t? value.error\n\t\t\t\t\t: `HTTP ${response.status}`;\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'oauth',\n\t\t\t\t`The authorization server rejected the token request (${oauthCode}).`\n\t\t\t);\n\t\t}\n\t\tconst tokens = parseTokenResponse(value);\n\t\tif (nonce)\n\t\t\tawait verifyIdToken({\n\t\t\t\tclientId: config.clientId,\n\t\t\t\tfetchImpl,\n\t\t\t\tidToken: tokens.id_token,\n\t\t\t\tissuer,\n\t\t\t\tjwksUri: metadata.jwks_uri,\n\t\t\t\tnonce,\n\t\t\t\tnow: now()\n\t\t\t});\n\n\t\treturn tokens;\n\t};\n\n\tconst acceptTokens = async (\n\t\ttokens: TokenResponse\n\t): Promise<MobileAuthTokens> => {\n\t\ttry {\n\t\t\tawait config.storage.set(REFRESH_KEY, tokens.refresh_token);\n\t\t} catch (cause) {\n\t\t\taccess = undefined;\n\t\t\tawait config.storage.remove(REFRESH_KEY).catch(() => undefined);\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'secure-storage',\n\t\t\t\t'The rotated refresh credential could not be saved securely.',\n\t\t\t\t{ cause }\n\t\t\t);\n\t\t}\n\t\taccess = {\n\t\t\taccessToken: tokens.access_token,\n\t\t\texpiresAt: now() + tokens.expires_in * 1000,\n\t\t\tidToken: tokens.id_token,\n\t\t\tscope: tokens.scope?.split(' ').filter(Boolean) ?? scopes,\n\t\t\ttokenType: 'Bearer'\n\t\t};\n\n\t\treturn { ...access, refreshToken: tokens.refresh_token };\n\t};\n\n\tconst rotateAccessToken = async () => {\n\t\tawait assertSecureStorage();\n\t\tconst refreshToken = await config.storage.get(REFRESH_KEY);\n\t\tif (!refreshToken)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'token',\n\t\t\t\t'This app has no renewable mobile session.'\n\t\t\t);\n\t\tconst metadata = await discovery();\n\t\tconst body = new URLSearchParams({\n\t\t\tclient_id: config.clientId,\n\t\t\tgrant_type: 'refresh_token',\n\t\t\trefresh_token: refreshToken\n\t\t});\n\t\tbody.set('resource', resource);\n\t\tconst tokens = await tokenRequest(metadata, body);\n\n\t\treturn (await acceptTokens(tokens)).accessToken;\n\t};\n\n\tconst refreshAccessToken = async () => {\n\t\tif (access && access.expiresAt - clockSkewMs > now())\n\t\t\treturn access.accessToken;\n\t\tif (refreshPromise) return refreshPromise;\n\t\trefreshPromise = rotateAccessToken().finally(() => {\n\t\t\trefreshPromise = undefined;\n\t\t});\n\n\t\treturn refreshPromise;\n\t};\n\n\tconst handleCallback = async (value: string) => {\n\t\tif (!exactRedirect(value, redirectUri))\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'callback',\n\t\t\t\t'The authorization callback does not match this app registration.'\n\t\t\t);\n\t\tconst url = new URL(value);\n\t\tconst pending = parsePending(await config.storage.get(PENDING_KEY));\n\t\tif (!pending || now() - pending.createdAt > PENDING_TTL_MS) {\n\t\t\tawait config.storage.remove(PENDING_KEY).catch(() => undefined);\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'callback',\n\t\t\t\t'The authorization transaction is missing or expired.'\n\t\t\t);\n\t\t}\n\t\tconst deferred = pendingSignIns.get(pending.state);\n\t\tconst reject = (error: unknown) => {\n\t\t\tpendingSignIns.delete(pending.state);\n\t\t\tvoid config.storage.remove(PENDING_KEY);\n\t\t\tdeferred?.reject(error);\n\t\t\tthrow error;\n\t\t};\n\t\tif (url.searchParams.get('state') !== pending.state)\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'callback',\n\t\t\t\t\t'The authorization callback state does not match.'\n\t\t\t\t)\n\t\t\t);\n\t\tif (url.searchParams.get('iss') !== issuer)\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'callback',\n\t\t\t\t\t'The authorization callback issuer does not match.'\n\t\t\t\t)\n\t\t\t);\n\t\tconst oauthError = url.searchParams.get('error');\n\t\tif (oauthError) {\n\t\t\tawait config.storage.remove(PENDING_KEY);\n\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'oauth',\n\t\t\t\t\t`Authorization failed (${oauthError}).`\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\t\tconst code = url.searchParams.get('code');\n\t\tif (!code)\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'callback',\n\t\t\t\t\t'The authorization callback contains no code.'\n\t\t\t\t)\n\t\t\t);\n\t\tawait config.storage.remove(PENDING_KEY);\n\t\ttry {\n\t\t\tconst metadata = await discovery();\n\t\t\tconst body = new URLSearchParams({\n\t\t\t\tclient_id: config.clientId,\n\t\t\t\tcode,\n\t\t\t\tcode_verifier: pending.verifier,\n\t\t\t\tgrant_type: 'authorization_code',\n\t\t\t\tredirect_uri: redirectUri\n\t\t\t});\n\t\t\tbody.set('resource', resource);\n\t\t\tconst tokens = await acceptTokens(\n\t\t\t\tawait tokenRequest(metadata, body, pending.nonce)\n\t\t\t);\n\t\t\tpendingSignIns.delete(pending.state);\n\t\t\tdeferred?.resolve(tokens);\n\n\t\t\treturn tokens;\n\t\t} catch (error) {\n\t\t\treturn reject(error);\n\t\t}\n\t};\n\n\tconst initialize = async () => {\n\t\tawait assertSecureStorage();\n\t\tstopLinks = await config.links.onOpen((url) => {\n\t\t\tif (exactRedirect(url, redirectUri))\n\t\t\t\tvoid handleCallback(url).catch(() => undefined);\n\t\t});\n\t\tif (config.lifecycle?.onResume)\n\t\t\tstopResume = await config.lifecycle.onResume(() => {\n\t\t\t\tvoid refreshAccessToken().catch(() => undefined);\n\t\t\t});\n\t\tconst launchUrl = await config.links.getLaunchUrl();\n\t\tif (launchUrl && exactRedirect(launchUrl, redirectUri))\n\t\t\tawait handleCallback(launchUrl);\n\t};\n\n\tconst start = () => {\n\t\tstartPromise ??= initialize();\n\n\t\treturn startPromise;\n\t};\n\n\tconst signIn = async (options: MobileAuthSignInOptions = {}) => {\n\t\tawait start();\n\t\tif (options.signal?.aborted)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'aborted',\n\t\t\t\t'Authorization was cancelled.'\n\t\t\t);\n\t\tconst metadata = await discovery();\n\t\tconst pending: PendingAuthorization = {\n\t\t\tcreatedAt: now(),\n\t\t\tnonce: randomValue(),\n\t\t\tstate: randomValue(),\n\t\t\tverifier: randomValue()\n\t\t};\n\t\tawait config.storage.set(PENDING_KEY, JSON.stringify(pending));\n\t\tconst url = new URL(metadata.authorization_endpoint);\n\t\turl.search = new URLSearchParams({\n\t\t\tclient_id: config.clientId,\n\t\t\tcode_challenge: await pkceChallenge(pending.verifier),\n\t\t\tcode_challenge_method: 'S256',\n\t\t\tnonce: pending.nonce,\n\t\t\tredirect_uri: redirectUri,\n\t\t\tresponse_type: 'code',\n\t\t\tscope: scopes.join(' '),\n\t\t\tstate: pending.state,\n\t\t\t...options.authorizationParameters\n\t\t}).toString();\n\t\turl.searchParams.set('resource', resource);\n\t\tconst result = new Promise<MobileAuthTokens>((resolve, reject) => {\n\t\t\tpendingSignIns.set(pending.state, { reject, resolve });\n\t\t\toptions.signal?.addEventListener(\n\t\t\t\t'abort',\n\t\t\t\t() => {\n\t\t\t\t\tpendingSignIns.delete(pending.state);\n\t\t\t\t\tvoid config.storage.remove(PENDING_KEY);\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t\t\t'aborted',\n\t\t\t\t\t\t\t'Authorization was cancelled.'\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\t{ once: true }\n\t\t\t);\n\t\t});\n\t\ttry {\n\t\t\tawait config.links.openExternal(url.href);\n\t\t} catch (error) {\n\t\t\tpendingSignIns.delete(pending.state);\n\t\t\tawait config.storage.remove(PENDING_KEY);\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn result;\n\t};\n\n\tconst authenticatedFetch = async (\n\t\tinput: RequestInfo | URL,\n\t\tinit?: RequestInit\n\t) => {\n\t\tconst original = new Request(input, init);\n\t\tif (!allowedOrigins.has(new URL(original.url).origin))\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'origin',\n\t\t\t\t'Mobile auth refused to send a credential to an unregistered origin.'\n\t\t\t);\n\t\tconst send = async (forceRefresh: boolean) => {\n\t\t\tif (forceRefresh) access = undefined;\n\t\t\tconst token = await refreshAccessToken();\n\t\t\tconst request = original.clone();\n\t\t\tconst headers = new Headers(request.headers);\n\t\t\theaders.set('authorization', `Bearer ${token}`);\n\n\t\t\treturn fetchImpl(\n\t\t\t\tnew Request(request, { credentials: 'omit', headers })\n\t\t\t);\n\t\t};\n\t\tconst response = await send(false);\n\n\t\treturn response.status === 401 ? send(true) : response;\n\t};\n\n\tconst optionalAuthenticatedFetch = async (\n\t\tinput: RequestInfo | URL,\n\t\tinit?: RequestInit\n\t) => {\n\t\tconst request = new Request(input, init);\n\t\tif (!allowedOrigins.has(new URL(request.url).origin))\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'origin',\n\t\t\t\t'Mobile auth refused to send a request outside an allowed origin.'\n\t\t\t);\n\t\tconst refreshToken = await config.storage.get(REFRESH_KEY);\n\t\tif (access || refreshToken) return authenticatedFetch(request);\n\n\t\treturn fetchImpl(new Request(request, { credentials: 'omit' }));\n\t};\n\n\tconst status = async () => {\n\t\ttry {\n\t\t\tconst metadata = await discovery();\n\t\t\tconst response = await authenticatedFetch(\n\t\t\t\tmetadata.userinfo_endpoint\n\t\t\t);\n\t\t\tif (response.status === 401) return null;\n\t\t\tif (!response.ok)\n\t\t\t\tthrow new MobileAuthError(\n\t\t\t\t\t'network',\n\t\t\t\t\t`User info failed with HTTP ${response.status}.`\n\t\t\t\t);\n\t\t\tconst user: unknown = await response.json();\n\t\t\tif (!isRecord(user) || typeof user.sub !== 'string')\n\t\t\t\tthrow new MobileAuthError(\n\t\t\t\t\t'token',\n\t\t\t\t\t'The user-info response is malformed.'\n\t\t\t\t);\n\n\t\t\treturn { ...user, sub: user.sub } satisfies MobileAuthUser;\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof MobileAuthError &&\n\t\t\t\t(error.code === 'oauth' || error.code === 'token')\n\t\t\t)\n\t\t\t\treturn null;\n\t\t\tthrow error;\n\t\t}\n\t};\n\n\tconst socketTicket = async (audience = resource) => {\n\t\tconst metadata = await discovery();\n\t\tif (!metadata.socket_ticket_endpoint)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'discovery',\n\t\t\t\t'The authorization server does not advertise WebSocket tickets.'\n\t\t\t);\n\t\tconst response = await authenticatedFetch(\n\t\t\tmetadata.socket_ticket_endpoint,\n\t\t\t{\n\t\t\t\tbody: JSON.stringify({ audience }),\n\t\t\t\theaders: { 'content-type': 'application/json' },\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t);\n\t\tconst body: unknown = await responseBody(response);\n\t\tif (!response.ok || !isRecord(body) || typeof body.ticket !== 'string')\n\t\t\tthrow new MobileAuthError(\n\t\t\t\tresponse.ok ? 'token' : 'oauth',\n\t\t\t\t`WebSocket ticket request failed with HTTP ${response.status}.`\n\t\t\t);\n\n\t\treturn body.ticket;\n\t};\n\n\tconst revokeRefreshToken = async (refreshToken: string) => {\n\t\tconst metadata = await discovery();\n\t\tif (metadata.revocation_endpoint)\n\t\t\tawait fetchImpl(metadata.revocation_endpoint, {\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tclient_id: config.clientId,\n\t\t\t\t\ttoken: refreshToken,\n\t\t\t\t\ttoken_type_hint: 'refresh_token'\n\t\t\t\t}),\n\t\t\t\tcredentials: 'omit',\n\t\t\t\theaders: {\n\t\t\t\t\t'content-type': 'application/x-www-form-urlencoded'\n\t\t\t\t},\n\t\t\t\tmethod: 'POST'\n\t\t\t});\n\t};\n\n\tconst signOut = async () => {\n\t\tconst refreshToken = await config.storage.get(REFRESH_KEY);\n\t\ttry {\n\t\t\tif (refreshToken) await revokeRefreshToken(refreshToken);\n\t\t} finally {\n\t\t\taccess = undefined;\n\t\t\tawait Promise.all([\n\t\t\t\tconfig.storage.remove(PENDING_KEY),\n\t\t\t\tconfig.storage.remove(REFRESH_KEY)\n\t\t\t]);\n\t\t}\n\t};\n\n\tconst stop = async () => {\n\t\tawait Promise.all([stopLinks?.(), stopResume?.()]);\n\t\tstopLinks = undefined;\n\t\tstopResume = undefined;\n\t\tstartPromise = undefined;\n\t};\n\n\treturn {\n\t\tfetch: authenticatedFetch,\n\t\tfetchOptional: optionalAuthenticatedFetch,\n\t\thandleCallback,\n\t\trefresh: refreshAccessToken,\n\t\tsignIn,\n\t\tsignOut,\n\t\tsocketTicket,\n\t\tstart,\n\t\tstatus,\n\t\tstop\n\t};\n};\n\nexport type MobileAuthClient = ReturnType<typeof createMobileAuthClient>;\n\n/** Adapts the native OAuth lifecycle behind the same createAuthClient API used\n * by web applications. Passwords stay out of the WebView request path; the\n * external authorization UI owns credential entry and MFA. */\nexport const createMobileAuthTransport = (\n\tclient: MobileAuthClient,\n\toptions: { baseUrl?: string } = {}\n): import('./createAuthClient').AuthClientTransport => ({\n\tfetch: (input, init) => {\n\t\tconst resolved =\n\t\t\toptions.baseUrl &&\n\t\t\t(typeof input === 'string' || input instanceof URL)\n\t\t\t\t? new URL(String(input), options.baseUrl)\n\t\t\t\t: input;\n\n\t\treturn client.fetchOptional(resolved, init);\n\t},\n\tsignInEmail: async ({ email }) => {\n\t\tawait client.signIn({\n\t\t\tauthorizationParameters: { login_hint: email }\n\t\t});\n\n\t\treturn { status: 'authenticated' };\n\t},\n\tsignOut: async () => {\n\t\tawait client.signOut();\n\n\t\treturn null;\n\t},\n\tsignUpEmail: async ({ email }) => {\n\t\tawait client.signIn({\n\t\t\tauthorizationParameters: {\n\t\t\t\tlogin_hint: email,\n\t\t\t\tscreen_hint: 'signup'\n\t\t\t}\n\t\t});\n\n\t\treturn { status: 'authenticated' };\n\t},\n\tstatus: async () => {\n\t\tconst user = await client.status();\n\n\t\treturn { user };\n\t}\n});\n\nexport { installAuthClientRuntimeTransport } from './runtimeTransport';\n"
6
+ "export type MobileAuthSecureStorage = {\n\tcapability?: () => Promise<{\n\t\tavailable: boolean;\n\t\tmessage?: string;\n\t}>;\n\tget(key: string): Promise<string | null>;\n\tremove(key: string): Promise<void>;\n\tset(key: string, value: string): Promise<void>;\n\t/** Serialize refresh-token rotation with a native background worker. */\n\twithLock?<T>(key: string, run: () => Promise<T>): Promise<T>;\n};\n\nexport type MobileAuthLinks = {\n\tgetLaunchUrl(): Promise<string | null>;\n\tonOpen(\n\t\tlistener: (url: string) => void\n\t): Promise<() => Promise<void> | void>;\n\topenExternal(url: string): Promise<void>;\n};\n\nexport type MobileAuthLifecycle = {\n\tonResume?(listener: () => void): Promise<() => Promise<void> | void>;\n};\n\nexport type MobileAuthDiscovery = {\n\tauthorization_endpoint: string;\n\tcode_challenge_methods_supported?: string[];\n\tissuer: string;\n\tjwks_uri: string;\n\trevocation_endpoint?: string;\n\tsocket_ticket_endpoint?: string;\n\ttoken_endpoint: string;\n\ttoken_endpoint_auth_methods_supported?: string[];\n\tuserinfo_endpoint: string;\n};\n\nexport type MobileAuthClientConfig = {\n\tallowedOrigins?: readonly string[];\n\tclientId: string;\n\tclockSkewMs?: number;\n\tfetch?: typeof globalThis.fetch;\n\tissuer: string;\n\tlifecycle?: MobileAuthLifecycle;\n\tlinks: MobileAuthLinks;\n\tnow?: () => number;\n\tredirectUri: string;\n\tresource?: string;\n\tscopes?: readonly string[];\n\tstorage: MobileAuthSecureStorage;\n};\n\nexport type MobileAuthSignInOptions = {\n\tauthorizationParameters?: Readonly<Record<string, string>>;\n\tsignal?: AbortSignal;\n};\n\nexport type MobileAuthTokens = {\n\taccessToken: string;\n\texpiresAt: number;\n\tidToken: string;\n\trefreshToken: string;\n\tscope: string[];\n\ttokenType: 'Bearer';\n};\n\nexport type MobileAuthUser = Record<string, unknown> & { sub: string };\n\nexport type MobileAuthPrincipal = {\n\tissuer: string;\n\tnamespace: string;\n\t/** Optional server-owned tenant/account partition from userinfo. */\n\tpartition?: string;\n\tsubject: string;\n};\n\nexport type MobileAuthErrorCode =\n\t| 'aborted'\n\t| 'callback'\n\t| 'discovery'\n\t| 'id-token'\n\t| 'network'\n\t| 'oauth'\n\t| 'origin'\n\t| 'secure-storage'\n\t| 'token';\n\nexport class MobileAuthError extends Error {\n\treadonly code: MobileAuthErrorCode;\n\treadonly cause?: unknown;\n\n\tconstructor(\n\t\tcode: MobileAuthErrorCode,\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown }\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'MobileAuthError';\n\t\tthis.code = code;\n\t\tthis.cause = options?.cause;\n\t}\n}\n\ntype PendingAuthorization = {\n\tcreatedAt: number;\n\tnonce: string;\n\tstate: string;\n\tverifier: string;\n};\n\ntype TokenResponse = {\n\taccess_token: string;\n\texpires_in: number;\n\tid_token: string;\n\trefresh_token: string;\n\tscope?: string;\n\ttoken_type: string;\n};\n\ntype DeferredSignIn = {\n\treject: (error: unknown) => void;\n\tresolve: (tokens: MobileAuthTokens) => void;\n};\n\nconst PENDING_KEY = 'oidc.pending';\nconst REFRESH_KEY = 'oidc.refresh';\nconst DEFAULT_CLOCK_SKEW_MS = 30_000;\nconst PENDING_TTL_MS = 10 * 60_000;\nconst RANDOM_BYTES = 32;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n\ttypeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst base64Url = (value: Uint8Array) => {\n\tlet binary = '';\n\tfor (const byte of value) binary += String.fromCharCode(byte);\n\n\treturn btoa(binary)\n\t\t.replaceAll('+', '-')\n\t\t.replaceAll('/', '_')\n\t\t.replace(/=+$/u, '');\n};\n\nconst decodeBase64Url = (value: string) => {\n\tconst normalized = value.replaceAll('-', '+').replaceAll('_', '/');\n\tconst padded = normalized.padEnd(\n\t\tnormalized.length + ((4 - (normalized.length % 4)) % 4),\n\t\t'='\n\t);\n\tconst binary = atob(padded);\n\n\treturn Uint8Array.from(binary, (character) => character.charCodeAt(0));\n};\n\nconst randomValue = () => {\n\tconst value = new Uint8Array(RANDOM_BYTES);\n\tcrypto.getRandomValues(value);\n\n\treturn base64Url(value);\n};\n\nconst pkceChallenge = async (verifier: string) =>\n\tbase64Url(\n\t\tnew Uint8Array(\n\t\t\tawait crypto.subtle.digest(\n\t\t\t\t'SHA-256',\n\t\t\t\tnew TextEncoder().encode(verifier)\n\t\t\t)\n\t\t)\n\t);\n\nconst normalizeIssuer = (value: string) => {\n\tconst issuer = new URL(value);\n\tconst loopback =\n\t\tissuer.protocol === 'http:' &&\n\t\t['127.0.0.1', '[::1]', 'localhost'].includes(issuer.hostname);\n\tif (issuer.protocol !== 'https:' && !loopback)\n\t\tthrow new TypeError('Mobile auth issuer must use HTTPS.');\n\tif (issuer.username || issuer.password || issuer.search || issuer.hash)\n\t\tthrow new TypeError(\n\t\t\t'Mobile auth issuer cannot contain credentials, query, or fragment.'\n\t\t);\n\tissuer.pathname = issuer.pathname.replace(/\\/$/u, '');\n\n\treturn issuer.href.replace(/\\/$/u, '');\n};\n\nconst exactRedirect = (actualValue: string, expectedValue: string) => {\n\tconst actual = new URL(actualValue);\n\tconst expected = new URL(expectedValue);\n\n\treturn (\n\t\tactual.protocol === expected.protocol &&\n\t\tactual.host === expected.host &&\n\t\tactual.pathname === expected.pathname &&\n\t\tactual.username === '' &&\n\t\tactual.password === ''\n\t);\n};\n\nconst parsePending = (value: string | null) => {\n\tif (value === null) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(value);\n\t\tif (\n\t\t\t!isRecord(parsed) ||\n\t\t\ttypeof parsed.createdAt !== 'number' ||\n\t\t\ttypeof parsed.nonce !== 'string' ||\n\t\t\ttypeof parsed.state !== 'string' ||\n\t\t\ttypeof parsed.verifier !== 'string'\n\t\t)\n\t\t\treturn undefined;\n\n\t\treturn {\n\t\t\tcreatedAt: parsed.createdAt,\n\t\t\tnonce: parsed.nonce,\n\t\t\tstate: parsed.state,\n\t\t\tverifier: parsed.verifier\n\t\t} satisfies PendingAuthorization;\n\t} catch {\n\t\treturn undefined;\n\t}\n};\n\nconst parseTokenResponse = (value: unknown) => {\n\tif (\n\t\t!isRecord(value) ||\n\t\ttypeof value.access_token !== 'string' ||\n\t\ttypeof value.expires_in !== 'number' ||\n\t\t!Number.isFinite(value.expires_in) ||\n\t\tvalue.expires_in <= 0 ||\n\t\ttypeof value.id_token !== 'string' ||\n\t\ttypeof value.refresh_token !== 'string' ||\n\t\ttypeof value.token_type !== 'string'\n\t)\n\t\tthrow new MobileAuthError('token', 'The token response is malformed.');\n\tif (value.token_type.toLowerCase() !== 'bearer')\n\t\tthrow new MobileAuthError(\n\t\t\t'token',\n\t\t\t`Unsupported mobile token type ${value.token_type}; DPoP is not enabled for this client.`\n\t\t);\n\n\treturn {\n\t\taccess_token: value.access_token,\n\t\texpires_in: value.expires_in,\n\t\tid_token: value.id_token,\n\t\trefresh_token: value.refresh_token,\n\t\tscope: typeof value.scope === 'string' ? value.scope : undefined,\n\t\ttoken_type: value.token_type\n\t} satisfies TokenResponse;\n};\n\nconst responseBody = async (response: Response) => {\n\tconst text = await response.text();\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn text;\n\t}\n};\n\nconst requireEndpoint = (value: unknown, name: string, issuer: string) => {\n\tif (typeof value !== 'string')\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t`OIDC discovery is missing ${name}.`\n\t\t);\n\tconst endpoint = new URL(value);\n\tif (endpoint.protocol !== 'https:' && new URL(issuer).protocol === 'https:')\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t`OIDC discovery ${name} must use HTTPS.`\n\t\t);\n\n\treturn endpoint.href;\n};\n\nconst parseDiscovery = (\n\tvalue: unknown,\n\tissuer: string\n): MobileAuthDiscovery => {\n\tif (!isRecord(value) || value.issuer !== issuer)\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t'OIDC discovery issuer does not match the configured issuer.'\n\t\t);\n\tconst methods = Array.isArray(value.code_challenge_methods_supported)\n\t\t? value.code_challenge_methods_supported.filter(\n\t\t\t\t(method): method is string => typeof method === 'string'\n\t\t\t)\n\t\t: undefined;\n\tif (!methods?.includes('S256'))\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t'OIDC provider does not advertise S256 PKCE.'\n\t\t);\n\tconst authMethods = Array.isArray(\n\t\tvalue.token_endpoint_auth_methods_supported\n\t)\n\t\t? value.token_endpoint_auth_methods_supported.filter(\n\t\t\t\t(method): method is string => typeof method === 'string'\n\t\t\t)\n\t\t: undefined;\n\tif (!authMethods?.includes('none'))\n\t\tthrow new MobileAuthError(\n\t\t\t'discovery',\n\t\t\t'OIDC provider does not accept public clients at the token endpoint.'\n\t\t);\n\n\treturn {\n\t\tauthorization_endpoint: requireEndpoint(\n\t\t\tvalue.authorization_endpoint,\n\t\t\t'authorization_endpoint',\n\t\t\tissuer\n\t\t),\n\t\tcode_challenge_methods_supported: methods,\n\t\tissuer,\n\t\tjwks_uri: requireEndpoint(value.jwks_uri, 'jwks_uri', issuer),\n\t\trevocation_endpoint:\n\t\t\ttypeof value.revocation_endpoint === 'string'\n\t\t\t\t? requireEndpoint(\n\t\t\t\t\t\tvalue.revocation_endpoint,\n\t\t\t\t\t\t'revocation_endpoint',\n\t\t\t\t\t\tissuer\n\t\t\t\t\t)\n\t\t\t\t: undefined,\n\t\tsocket_ticket_endpoint:\n\t\t\ttypeof value.socket_ticket_endpoint === 'string'\n\t\t\t\t? requireEndpoint(\n\t\t\t\t\t\tvalue.socket_ticket_endpoint,\n\t\t\t\t\t\t'socket_ticket_endpoint',\n\t\t\t\t\t\tissuer\n\t\t\t\t\t)\n\t\t\t\t: undefined,\n\t\ttoken_endpoint: requireEndpoint(\n\t\t\tvalue.token_endpoint,\n\t\t\t'token_endpoint',\n\t\t\tissuer\n\t\t),\n\t\ttoken_endpoint_auth_methods_supported: authMethods,\n\t\tuserinfo_endpoint: requireEndpoint(\n\t\t\tvalue.userinfo_endpoint,\n\t\t\t'userinfo_endpoint',\n\t\t\tissuer\n\t\t)\n\t};\n};\n\nconst verifyIdToken = async ({\n\tclientId,\n\tfetchImpl,\n\tidToken,\n\tissuer,\n\tjwksUri,\n\tnonce,\n\tnow\n}: {\n\tclientId: string;\n\tfetchImpl: typeof globalThis.fetch;\n\tidToken: string;\n\tissuer: string;\n\tjwksUri: string;\n\tnonce: string;\n\tnow: number;\n}) => {\n\tconst [encodedHeader, encodedPayload, encodedSignature, ...extra] =\n\t\tidToken.split('.');\n\tif (!encodedHeader || !encodedPayload || !encodedSignature || extra.length)\n\t\tthrow new MobileAuthError('id-token', 'The ID token is malformed.');\n\tlet header: unknown;\n\tlet payload: unknown;\n\ttry {\n\t\theader = JSON.parse(\n\t\t\tnew TextDecoder().decode(decodeBase64Url(encodedHeader))\n\t\t);\n\t\tpayload = JSON.parse(\n\t\t\tnew TextDecoder().decode(decodeBase64Url(encodedPayload))\n\t\t);\n\t} catch (cause) {\n\t\tthrow new MobileAuthError('id-token', 'The ID token is malformed.', {\n\t\t\tcause\n\t\t});\n\t}\n\tif (\n\t\t!isRecord(header) ||\n\t\theader.alg !== 'ES256' ||\n\t\ttypeof header.kid !== 'string' ||\n\t\t!isRecord(payload)\n\t)\n\t\tthrow new MobileAuthError(\n\t\t\t'id-token',\n\t\t\t'The ID token header or claims are invalid.'\n\t\t);\n\tconst response = await fetchImpl(jwksUri, { cache: 'no-store' });\n\tif (!response.ok)\n\t\tthrow new MobileAuthError(\n\t\t\t'network',\n\t\t\t'Unable to fetch OIDC signing keys.'\n\t\t);\n\tconst body: unknown = await response.json();\n\tconst keys = isRecord(body) && Array.isArray(body.keys) ? body.keys : [];\n\tconst jwk = keys.find(\n\t\t(candidate): candidate is JsonWebKey & { kid: string } =>\n\t\t\tisRecord(candidate) && candidate.kid === header.kid\n\t);\n\tif (!jwk)\n\t\tthrow new MobileAuthError(\n\t\t\t'id-token',\n\t\t\t'The ID token signing key is unknown.'\n\t\t);\n\tconst key = await crypto.subtle.importKey(\n\t\t'jwk',\n\t\tjwk,\n\t\t{ hash: 'SHA-256', name: 'ECDSA', namedCurve: 'P-256' },\n\t\tfalse,\n\t\t['verify']\n\t);\n\tconst valid = await crypto.subtle.verify(\n\t\t{ hash: 'SHA-256', name: 'ECDSA' },\n\t\tkey,\n\t\tdecodeBase64Url(encodedSignature),\n\t\tnew TextEncoder().encode(`${encodedHeader}.${encodedPayload}`)\n\t);\n\tconst audience = payload.aud;\n\tif (\n\t\t!valid ||\n\t\tpayload.iss !== issuer ||\n\t\t!(\n\t\t\taudience === clientId ||\n\t\t\t(Array.isArray(audience) && audience.includes(clientId))\n\t\t) ||\n\t\tpayload.nonce !== nonce ||\n\t\ttypeof payload.exp !== 'number' ||\n\t\tpayload.exp * 1000 <= now\n\t)\n\t\tthrow new MobileAuthError(\n\t\t\t'id-token',\n\t\t\t'The ID token signature or claims are invalid.'\n\t\t);\n};\n\nexport const createMobileAuthClient = (config: MobileAuthClientConfig) => {\n\tconst issuer = normalizeIssuer(config.issuer);\n\tconst redirectUri = new URL(config.redirectUri).href;\n\tconst fetchImpl = config.fetch ?? globalThis.fetch;\n\tconst now = config.now ?? Date.now;\n\tconst clockSkewMs = config.clockSkewMs ?? DEFAULT_CLOCK_SKEW_MS;\n\tconst scopes = [...new Set(config.scopes ?? ['openid', 'profile'])];\n\tconst resource = config.resource ?? issuer;\n\tif (!scopes.includes('openid')) scopes.unshift('openid');\n\tconst allowedOrigins = new Set(\n\t\t(config.allowedOrigins ?? [new URL(issuer).origin]).map(\n\t\t\t(value) => new URL(value).origin\n\t\t)\n\t);\n\tlet discoveryPromise: Promise<MobileAuthDiscovery> | undefined;\n\tlet access: Omit<MobileAuthTokens, 'refreshToken'> | undefined;\n\tlet refreshPromise: Promise<string> | undefined;\n\tlet stopLinks: (() => Promise<void> | void) | undefined;\n\tlet stopResume: (() => Promise<void> | void) | undefined;\n\tlet startPromise: Promise<void> | undefined;\n\tconst pendingSignIns = new Map<string, DeferredSignIn>();\n\tlet currentPrincipal: MobileAuthPrincipal | null | undefined;\n\tconst principalListeners = new Set<\n\t\t(principal: MobileAuthPrincipal | null) => void\n\t>();\n\tconst publishPrincipal = (principal: MobileAuthPrincipal | null) => {\n\t\tif (\n\t\t\tcurrentPrincipal !== undefined &&\n\t\t\tcurrentPrincipal?.namespace === principal?.namespace\n\t\t)\n\t\t\treturn;\n\t\tcurrentPrincipal = principal;\n\t\tfor (const listener of principalListeners) listener(principal);\n\t};\n\tconst principalFor = async (\n\t\tuser: MobileAuthUser\n\t): Promise<MobileAuthPrincipal> => {\n\t\tconst partition =\n\t\t\ttypeof user.absolutejs_sync_partition === 'string' &&\n\t\t\tuser.absolutejs_sync_partition.length > 0\n\t\t\t\t? user.absolutejs_sync_partition\n\t\t\t\t: undefined;\n\t\tconst digest = await crypto.subtle.digest(\n\t\t\t'SHA-256',\n\t\t\tnew TextEncoder().encode(\n\t\t\t\tJSON.stringify([\n\t\t\t\t\tissuer,\n\t\t\t\t\tconfig.clientId,\n\t\t\t\t\tuser.sub,\n\t\t\t\t\tpartition ?? null\n\t\t\t\t])\n\t\t\t)\n\t\t);\n\n\t\treturn {\n\t\t\tissuer,\n\t\t\tnamespace: `auth:v1:${base64Url(new Uint8Array(digest))}`,\n\t\t\t...(partition === undefined ? {} : { partition }),\n\t\t\tsubject: user.sub\n\t\t};\n\t};\n\n\tconst fetchDiscovery = async () => {\n\t\tconst url = new URL('/.well-known/openid-configuration', `${issuer}/`);\n\t\tconst response = await fetchImpl(url, {\n\t\t\tcache: 'no-store',\n\t\t\theaders: { accept: 'application/json' }\n\t\t});\n\t\tif (!response.ok)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'discovery',\n\t\t\t\t`OIDC discovery failed with HTTP ${response.status}.`\n\t\t\t);\n\n\t\treturn parseDiscovery(await response.json(), issuer);\n\t};\n\n\tconst discovery = () => {\n\t\tdiscoveryPromise ??= fetchDiscovery();\n\n\t\treturn discoveryPromise;\n\t};\n\n\tconst assertSecureStorage = async () => {\n\t\tconst capability = await config.storage.capability?.();\n\t\tif (capability && !capability.available)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'secure-storage',\n\t\t\t\tcapability.message ??\n\t\t\t\t\t'Native secure credential storage is unavailable.'\n\t\t\t);\n\t};\n\n\tconst tokenRequest = async (\n\t\tmetadata: MobileAuthDiscovery,\n\t\tbody: URLSearchParams,\n\t\tnonce?: string\n\t) => {\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetchImpl(metadata.token_endpoint, {\n\t\t\t\tbody,\n\t\t\t\tcredentials: 'omit',\n\t\t\t\theaders: {\n\t\t\t\t\taccept: 'application/json',\n\t\t\t\t\t'content-type': 'application/x-www-form-urlencoded'\n\t\t\t\t},\n\t\t\t\tmethod: 'POST'\n\t\t\t});\n\t\t} catch (cause) {\n\t\t\tthrow new MobileAuthError('network', 'The token request failed.', {\n\t\t\t\tcause\n\t\t\t});\n\t\t}\n\t\tconst value = await responseBody(response);\n\t\tif (!response.ok) {\n\t\t\tconst oauthCode =\n\t\t\t\tisRecord(value) && typeof value.error === 'string'\n\t\t\t\t\t? value.error\n\t\t\t\t\t: `HTTP ${response.status}`;\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'oauth',\n\t\t\t\t`The authorization server rejected the token request (${oauthCode}).`\n\t\t\t);\n\t\t}\n\t\tconst tokens = parseTokenResponse(value);\n\t\tif (nonce)\n\t\t\tawait verifyIdToken({\n\t\t\t\tclientId: config.clientId,\n\t\t\t\tfetchImpl,\n\t\t\t\tidToken: tokens.id_token,\n\t\t\t\tissuer,\n\t\t\t\tjwksUri: metadata.jwks_uri,\n\t\t\t\tnonce,\n\t\t\t\tnow: now()\n\t\t\t});\n\n\t\treturn tokens;\n\t};\n\n\tconst acceptTokens = async (\n\t\ttokens: TokenResponse\n\t): Promise<MobileAuthTokens> => {\n\t\ttry {\n\t\t\tawait config.storage.set(REFRESH_KEY, tokens.refresh_token);\n\t\t} catch (cause) {\n\t\t\taccess = undefined;\n\t\t\tawait config.storage.remove(REFRESH_KEY).catch(() => undefined);\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'secure-storage',\n\t\t\t\t'The rotated refresh credential could not be saved securely.',\n\t\t\t\t{ cause }\n\t\t\t);\n\t\t}\n\t\taccess = {\n\t\t\taccessToken: tokens.access_token,\n\t\t\texpiresAt: now() + tokens.expires_in * 1000,\n\t\t\tidToken: tokens.id_token,\n\t\t\tscope: tokens.scope?.split(' ').filter(Boolean) ?? scopes,\n\t\t\ttokenType: 'Bearer'\n\t\t};\n\n\t\treturn { ...access, refreshToken: tokens.refresh_token };\n\t};\n\n\tconst rotateAccessToken = async () => {\n\t\tawait assertSecureStorage();\n\t\tconst exchange = async () => {\n\t\t\tconst refreshToken = await config.storage.get(REFRESH_KEY);\n\t\t\tif (!refreshToken)\n\t\t\t\tthrow new MobileAuthError(\n\t\t\t\t\t'token',\n\t\t\t\t\t'This app has no renewable mobile session.'\n\t\t\t\t);\n\t\t\tconst metadata = await discovery();\n\t\t\tconst body = new URLSearchParams({\n\t\t\t\tclient_id: config.clientId,\n\t\t\t\tgrant_type: 'refresh_token',\n\t\t\t\trefresh_token: refreshToken\n\t\t\t});\n\t\t\tbody.set('resource', resource);\n\t\t\tconst tokens = await tokenRequest(metadata, body);\n\n\t\t\treturn (await acceptTokens(tokens)).accessToken;\n\t\t};\n\n\t\treturn config.storage.withLock\n\t\t\t? config.storage.withLock(REFRESH_KEY, exchange)\n\t\t\t: exchange();\n\t};\n\n\tconst refreshAccessToken = async () => {\n\t\tif (access && access.expiresAt - clockSkewMs > now())\n\t\t\treturn access.accessToken;\n\t\tif (refreshPromise) return refreshPromise;\n\t\trefreshPromise = rotateAccessToken().finally(() => {\n\t\t\trefreshPromise = undefined;\n\t\t});\n\n\t\treturn refreshPromise;\n\t};\n\n\tconst handleCallback = async (value: string) => {\n\t\tif (!exactRedirect(value, redirectUri))\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'callback',\n\t\t\t\t'The authorization callback does not match this app registration.'\n\t\t\t);\n\t\tconst url = new URL(value);\n\t\tconst pending = parsePending(await config.storage.get(PENDING_KEY));\n\t\tif (!pending || now() - pending.createdAt > PENDING_TTL_MS) {\n\t\t\tawait config.storage.remove(PENDING_KEY).catch(() => undefined);\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'callback',\n\t\t\t\t'The authorization transaction is missing or expired.'\n\t\t\t);\n\t\t}\n\t\tconst deferred = pendingSignIns.get(pending.state);\n\t\tconst reject = (error: unknown) => {\n\t\t\tpendingSignIns.delete(pending.state);\n\t\t\tvoid config.storage.remove(PENDING_KEY);\n\t\t\tdeferred?.reject(error);\n\t\t\tthrow error;\n\t\t};\n\t\tif (url.searchParams.get('state') !== pending.state)\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'callback',\n\t\t\t\t\t'The authorization callback state does not match.'\n\t\t\t\t)\n\t\t\t);\n\t\tif (url.searchParams.get('iss') !== issuer)\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'callback',\n\t\t\t\t\t'The authorization callback issuer does not match.'\n\t\t\t\t)\n\t\t\t);\n\t\tconst oauthError = url.searchParams.get('error');\n\t\tif (oauthError) {\n\t\t\tawait config.storage.remove(PENDING_KEY);\n\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'oauth',\n\t\t\t\t\t`Authorization failed (${oauthError}).`\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\t\tconst code = url.searchParams.get('code');\n\t\tif (!code)\n\t\t\treturn reject(\n\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t'callback',\n\t\t\t\t\t'The authorization callback contains no code.'\n\t\t\t\t)\n\t\t\t);\n\t\tawait config.storage.remove(PENDING_KEY);\n\t\ttry {\n\t\t\tconst metadata = await discovery();\n\t\t\tconst body = new URLSearchParams({\n\t\t\t\tclient_id: config.clientId,\n\t\t\t\tcode,\n\t\t\t\tcode_verifier: pending.verifier,\n\t\t\t\tgrant_type: 'authorization_code',\n\t\t\t\tredirect_uri: redirectUri\n\t\t\t});\n\t\t\tbody.set('resource', resource);\n\t\t\tconst tokens = await acceptTokens(\n\t\t\t\tawait tokenRequest(metadata, body, pending.nonce)\n\t\t\t);\n\t\t\tpendingSignIns.delete(pending.state);\n\t\t\tdeferred?.resolve(tokens);\n\n\t\t\treturn tokens;\n\t\t} catch (error) {\n\t\t\treturn reject(error);\n\t\t}\n\t};\n\n\tconst initialize = async () => {\n\t\tawait assertSecureStorage();\n\t\tstopLinks = await config.links.onOpen((url) => {\n\t\t\tif (exactRedirect(url, redirectUri))\n\t\t\t\tvoid handleCallback(url).catch(() => undefined);\n\t\t});\n\t\tif (config.lifecycle?.onResume)\n\t\t\tstopResume = await config.lifecycle.onResume(() => {\n\t\t\t\tvoid refreshAccessToken().catch(() => undefined);\n\t\t\t});\n\t\tconst launchUrl = await config.links.getLaunchUrl();\n\t\tif (launchUrl && exactRedirect(launchUrl, redirectUri))\n\t\t\tawait handleCallback(launchUrl);\n\t};\n\n\tconst start = () => {\n\t\tstartPromise ??= initialize();\n\n\t\treturn startPromise;\n\t};\n\n\tconst signIn = async (options: MobileAuthSignInOptions = {}) => {\n\t\tawait start();\n\t\tif (options.signal?.aborted)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'aborted',\n\t\t\t\t'Authorization was cancelled.'\n\t\t\t);\n\t\tconst metadata = await discovery();\n\t\tconst pending: PendingAuthorization = {\n\t\t\tcreatedAt: now(),\n\t\t\tnonce: randomValue(),\n\t\t\tstate: randomValue(),\n\t\t\tverifier: randomValue()\n\t\t};\n\t\tawait config.storage.set(PENDING_KEY, JSON.stringify(pending));\n\t\tconst url = new URL(metadata.authorization_endpoint);\n\t\turl.search = new URLSearchParams({\n\t\t\tclient_id: config.clientId,\n\t\t\tcode_challenge: await pkceChallenge(pending.verifier),\n\t\t\tcode_challenge_method: 'S256',\n\t\t\tnonce: pending.nonce,\n\t\t\tredirect_uri: redirectUri,\n\t\t\tresponse_type: 'code',\n\t\t\tscope: scopes.join(' '),\n\t\t\tstate: pending.state,\n\t\t\t...options.authorizationParameters\n\t\t}).toString();\n\t\turl.searchParams.set('resource', resource);\n\t\tconst result = new Promise<MobileAuthTokens>((resolve, reject) => {\n\t\t\tpendingSignIns.set(pending.state, { reject, resolve });\n\t\t\toptions.signal?.addEventListener(\n\t\t\t\t'abort',\n\t\t\t\t() => {\n\t\t\t\t\tpendingSignIns.delete(pending.state);\n\t\t\t\t\tvoid config.storage.remove(PENDING_KEY);\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew MobileAuthError(\n\t\t\t\t\t\t\t'aborted',\n\t\t\t\t\t\t\t'Authorization was cancelled.'\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\t{ once: true }\n\t\t\t);\n\t\t});\n\t\ttry {\n\t\t\tawait config.links.openExternal(url.href);\n\t\t} catch (error) {\n\t\t\tpendingSignIns.delete(pending.state);\n\t\t\tawait config.storage.remove(PENDING_KEY);\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn result;\n\t};\n\n\tconst authenticatedFetch = async (\n\t\tinput: RequestInfo | URL,\n\t\tinit?: RequestInit\n\t) => {\n\t\tconst original = new Request(input, init);\n\t\tif (!allowedOrigins.has(new URL(original.url).origin))\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'origin',\n\t\t\t\t'Mobile auth refused to send a credential to an unregistered origin.'\n\t\t\t);\n\t\tconst send = async (forceRefresh: boolean) => {\n\t\t\tif (forceRefresh) access = undefined;\n\t\t\tconst token = await refreshAccessToken();\n\t\t\tconst request = original.clone();\n\t\t\tconst headers = new Headers(request.headers);\n\t\t\theaders.set('authorization', `Bearer ${token}`);\n\n\t\t\treturn fetchImpl(\n\t\t\t\tnew Request(request, { credentials: 'omit', headers })\n\t\t\t);\n\t\t};\n\t\tconst response = await send(false);\n\n\t\treturn response.status === 401 ? send(true) : response;\n\t};\n\n\tconst optionalAuthenticatedFetch = async (\n\t\tinput: RequestInfo | URL,\n\t\tinit?: RequestInit\n\t) => {\n\t\tconst request = new Request(input, init);\n\t\tif (!allowedOrigins.has(new URL(request.url).origin))\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'origin',\n\t\t\t\t'Mobile auth refused to send a request outside an allowed origin.'\n\t\t\t);\n\t\tconst refreshToken = await config.storage.get(REFRESH_KEY);\n\t\tif (access || refreshToken) return authenticatedFetch(request);\n\n\t\treturn fetchImpl(new Request(request, { credentials: 'omit' }));\n\t};\n\tconst signedOut = () => {\n\t\tpublishPrincipal(null);\n\n\t\treturn null;\n\t};\n\n\tconst status = async () => {\n\t\ttry {\n\t\t\tconst metadata = await discovery();\n\t\t\tconst response = await authenticatedFetch(\n\t\t\t\tmetadata.userinfo_endpoint\n\t\t\t);\n\t\t\tif (response.status === 401) return signedOut();\n\t\t\tif (!response.ok)\n\t\t\t\tthrow new MobileAuthError(\n\t\t\t\t\t'network',\n\t\t\t\t\t`User info failed with HTTP ${response.status}.`\n\t\t\t\t);\n\t\t\tconst user: unknown = await response.json();\n\t\t\tif (!isRecord(user) || typeof user.sub !== 'string')\n\t\t\t\tthrow new MobileAuthError(\n\t\t\t\t\t'token',\n\t\t\t\t\t'The user-info response is malformed.'\n\t\t\t\t);\n\n\t\t\tconst normalized = {\n\t\t\t\t...user,\n\t\t\t\tsub: user.sub\n\t\t\t} satisfies MobileAuthUser;\n\t\t\tpublishPrincipal(await principalFor(normalized));\n\n\t\t\treturn normalized;\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\t!(\n\t\t\t\t\terror instanceof MobileAuthError &&\n\t\t\t\t\t(error.code === 'oauth' || error.code === 'token')\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tthrow error;\n\n\t\t\treturn signedOut();\n\t\t}\n\t};\n\n\tconst socketTicket = async (audience = resource) => {\n\t\tconst metadata = await discovery();\n\t\tif (!metadata.socket_ticket_endpoint)\n\t\t\tthrow new MobileAuthError(\n\t\t\t\t'discovery',\n\t\t\t\t'The authorization server does not advertise WebSocket tickets.'\n\t\t\t);\n\t\tconst response = await authenticatedFetch(\n\t\t\tmetadata.socket_ticket_endpoint,\n\t\t\t{\n\t\t\t\tbody: JSON.stringify({ audience }),\n\t\t\t\theaders: { 'content-type': 'application/json' },\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t);\n\t\tconst body: unknown = await responseBody(response);\n\t\tif (!response.ok || !isRecord(body) || typeof body.ticket !== 'string')\n\t\t\tthrow new MobileAuthError(\n\t\t\t\tresponse.ok ? 'token' : 'oauth',\n\t\t\t\t`WebSocket ticket request failed with HTTP ${response.status}.`\n\t\t\t);\n\n\t\treturn body.ticket;\n\t};\n\n\tconst revokeRefreshToken = async (refreshToken: string) => {\n\t\tconst metadata = await discovery();\n\t\tif (metadata.revocation_endpoint)\n\t\t\tawait fetchImpl(metadata.revocation_endpoint, {\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tclient_id: config.clientId,\n\t\t\t\t\ttoken: refreshToken,\n\t\t\t\t\ttoken_type_hint: 'refresh_token'\n\t\t\t\t}),\n\t\t\t\tcredentials: 'omit',\n\t\t\t\theaders: {\n\t\t\t\t\t'content-type': 'application/x-www-form-urlencoded'\n\t\t\t\t},\n\t\t\t\tmethod: 'POST'\n\t\t\t});\n\t};\n\n\tconst signOut = async () => {\n\t\tconst refreshToken = await config.storage.get(REFRESH_KEY);\n\t\ttry {\n\t\t\tif (refreshToken) await revokeRefreshToken(refreshToken);\n\t\t} finally {\n\t\t\taccess = undefined;\n\t\t\tawait Promise.all([\n\t\t\t\tconfig.storage.remove(PENDING_KEY),\n\t\t\t\tconfig.storage.remove(REFRESH_KEY)\n\t\t\t]);\n\t\t\tpublishPrincipal(null);\n\t\t}\n\t};\n\n\tconst principal = async () => {\n\t\tawait status();\n\n\t\treturn currentPrincipal ?? null;\n\t};\n\n\tconst onPrincipalChange = (\n\t\tlistener: (principal: MobileAuthPrincipal | null) => void\n\t) => {\n\t\tprincipalListeners.add(listener);\n\t\tif (currentPrincipal !== undefined) listener(currentPrincipal);\n\n\t\treturn () => {\n\t\t\tprincipalListeners.delete(listener);\n\t\t};\n\t};\n\n\tconst stop = async () => {\n\t\tawait Promise.all([stopLinks?.(), stopResume?.()]);\n\t\tstopLinks = undefined;\n\t\tstopResume = undefined;\n\t\tstartPromise = undefined;\n\t};\n\n\treturn {\n\t\tfetch: authenticatedFetch,\n\t\tfetchOptional: optionalAuthenticatedFetch,\n\t\thandleCallback,\n\t\tonPrincipalChange,\n\t\tprincipal,\n\t\trefresh: refreshAccessToken,\n\t\tsignIn,\n\t\tsignOut,\n\t\tsocketTicket,\n\t\tstart,\n\t\tstatus,\n\t\tstop\n\t};\n};\n\nexport type MobileAuthClient = ReturnType<typeof createMobileAuthClient>;\n\n/** Adapts the native OAuth lifecycle behind the same createAuthClient API used\n * by web applications. Passwords stay out of the WebView request path; the\n * external authorization UI owns credential entry and MFA. */\nexport const createMobileAuthTransport = (\n\tclient: MobileAuthClient,\n\toptions: { baseUrl?: string } = {}\n): import('./createAuthClient').AuthClientTransport => ({\n\tfetch: (input, init) => {\n\t\tconst resolved =\n\t\t\toptions.baseUrl &&\n\t\t\t(typeof input === 'string' || input instanceof URL)\n\t\t\t\t? new URL(String(input), options.baseUrl)\n\t\t\t\t: input;\n\n\t\treturn client.fetchOptional(resolved, init);\n\t},\n\tsignInEmail: async ({ email }) => {\n\t\tawait client.signIn({\n\t\t\tauthorizationParameters: { login_hint: email }\n\t\t});\n\n\t\treturn { status: 'authenticated' };\n\t},\n\tsignOut: async () => {\n\t\tawait client.signOut();\n\n\t\treturn null;\n\t},\n\tsignUpEmail: async ({ email }) => {\n\t\tawait client.signIn({\n\t\t\tauthorizationParameters: {\n\t\t\t\tlogin_hint: email,\n\t\t\t\tscreen_hint: 'signup'\n\t\t\t}\n\t\t});\n\n\t\treturn { status: 'authenticated' };\n\t},\n\tstatus: async () => {\n\t\tconst user = await client.status();\n\n\t\treturn { user };\n\t}\n});\n\nexport { installAuthClientRuntimeTransport } from './runtimeTransport';\n"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "E6C9C1D1A29260E464756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "949AEA9AEBBABE7C64756E2164756E21",
10
10
  "names": []
11
11
  }
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { Elysia } from 'elysia';
2
2
  import type { AuthConfig } from './types';
3
3
  export declare const auth: <UserType>(configuration: AuthConfig<UserType>) => Promise<Elysia<"", "local", {
4
- decorator: {};
4
+ decorator: {
5
+ absoluteAuthSync: import("./syncBridge").AbsoluteAuthSyncBridge<UserType> | undefined;
6
+ };
5
7
  store: {
6
8
  session: import("./types").SessionRecord<UserType>;
7
9
  unregisteredSession: import("./types").UnregisteredSessionRecord;
@@ -60,6 +62,13 @@ export declare const auth: <UserType>(configuration: AuthConfig<UserType>) => Pr
60
62
  typebox: {};
61
63
  error: [];
62
64
  }, import("elysia/types").DefaultMetadata & ((import("elysia/types").DefaultMetadata & ({
65
+ schema: {};
66
+ schemas: {};
67
+ macro: {};
68
+ macroFn: {};
69
+ parser: {};
70
+ response: {};
71
+ } & ({
63
72
  schema: {};
64
73
  schemas: import("elysia").UnwrapRoute<{
65
74
  cookie: import("elysia").TCookieObject<{
@@ -120,7 +129,7 @@ export declare const auth: <UserType>(configuration: AuthConfig<UserType>) => Pr
120
129
  readonly message: "User is not authenticated";
121
130
  }) => AuthFailReturn_3) | undefined) => Promise<import("elysia").ElysiaStatus<"Bad Request", "Cookies are missing", 400> | import("elysia").ElysiaStatus<"Unauthorized", "User is not authenticated", 401> | import("elysia").ElysiaStatus<"Forbidden", "Insufficient permissions", 403> | AuthReturn | NonNullable<AuthFailReturn_3>>;
122
131
  }>;
123
- })))) & {
132
+ }))))) & {
124
133
  schema: {};
125
134
  schemas: {};
126
135
  macro: {};
@@ -141,7 +150,9 @@ export declare const auth: <UserType>(configuration: AuthConfig<UserType>) => Pr
141
150
  }>>;
142
151
  export declare const createAuthApplications: <UserType>(configuration: AuthConfig<UserType>) => Promise<{
143
152
  authContext: Elysia<"", "local", {
144
- decorator: {};
153
+ decorator: {
154
+ absoluteAuthSync: import("./syncBridge").AbsoluteAuthSyncBridge<UserType> | undefined;
155
+ };
145
156
  store: {
146
157
  session: import("./types").SessionRecord<UserType>;
147
158
  unregisteredSession: import("./types").UnregisteredSessionRecord;
@@ -200,6 +211,13 @@ export declare const createAuthApplications: <UserType>(configuration: AuthConfi
200
211
  typebox: {};
201
212
  error: [];
202
213
  }, (import("elysia/types").DefaultMetadata & ({
214
+ schema: {};
215
+ schemas: {};
216
+ macro: {};
217
+ macroFn: {};
218
+ parser: {};
219
+ response: {};
220
+ } & ({
203
221
  schema: {};
204
222
  schemas: import("elysia").UnwrapRoute<{
205
223
  cookie: import("elysia").TCookieObject<{
@@ -260,7 +278,7 @@ export declare const createAuthApplications: <UserType>(configuration: AuthConfi
260
278
  readonly message: "User is not authenticated";
261
279
  }) => AuthFailReturn_3) | undefined) => Promise<import("elysia").ElysiaStatus<"Bad Request", "Cookies are missing", 400> | import("elysia").ElysiaStatus<"Unauthorized", "User is not authenticated", 401> | import("elysia").ElysiaStatus<"Forbidden", "Insufficient permissions", 403> | AuthReturn | NonNullable<AuthFailReturn_3>>;
262
280
  }>;
263
- })))) & {
281
+ }))))) & {
264
282
  schema: {};
265
283
  schemas: {};
266
284
  macro: {};
@@ -3851,6 +3869,7 @@ export { createNeonLinkedProviderStores, createNeonOAuthLinkedProviderCredential
3851
3869
  export { createInMemoryLinkedProviderStores } from './linkedProviders/inMemoryStores';
3852
3870
  export { protectRoutePlugin } from './routes/protectRoute';
3853
3871
  export { requireAuthPlugin } from './routes/requireAuth';
3872
+ export { createAbsoluteAuthSyncBridge, type AbsoluteAuthSyncBridge, type AbsoluteAuthSyncContext } from './syncBridge';
3854
3873
  export { sessionRoutes } from './routes/sessions';
3855
3874
  export { stepUpPlugin } from './routes/stepUp';
3856
3875
  export * from './session/sessionsConfig';
package/dist/index.js CHANGED
@@ -4775,6 +4775,75 @@ var stepUpPlugin = ({
4775
4775
  })
4776
4776
  })).as("global");
4777
4777
 
4778
+ // src/oidc/socketTickets.ts
4779
+ init_crypto();
4780
+ var DEFAULT_SOCKET_TICKET_TTL_MS = 30000;
4781
+ var TICKET_BYTES = 32;
4782
+ var consumeSocketTicket = async ({
4783
+ audience,
4784
+ getUser,
4785
+ now = Date.now(),
4786
+ store,
4787
+ ticket
4788
+ }) => {
4789
+ const record = await store.consumeTicket(await hashToken(ticket), now);
4790
+ if (!record || record.audience !== audience)
4791
+ return;
4792
+ const user = await getUser(record.subject);
4793
+ if (user === null)
4794
+ return;
4795
+ return {
4796
+ audience: record.audience,
4797
+ clientId: record.clientId,
4798
+ kind: "access-token",
4799
+ scopes: [...record.scopes],
4800
+ subject: record.subject,
4801
+ user
4802
+ };
4803
+ };
4804
+ var issueSocketTicket = async ({
4805
+ audience,
4806
+ clientId,
4807
+ now = Date.now(),
4808
+ scopes,
4809
+ store,
4810
+ subject,
4811
+ ttlMs = DEFAULT_SOCKET_TICKET_TTL_MS
4812
+ }) => {
4813
+ if (!Number.isFinite(ttlMs) || ttlMs <= 0)
4814
+ throw new Error("socketTicketTtlMs must be positive");
4815
+ const ticket = `ast_${generateSecureToken(TICKET_BYTES)}`;
4816
+ await store.saveTicket({
4817
+ audience,
4818
+ clientId,
4819
+ expiresAt: now + ttlMs,
4820
+ scopes: [...scopes],
4821
+ subject,
4822
+ ticketHash: await hashToken(ticket)
4823
+ });
4824
+ return { expiresInMs: ttlMs, ticket };
4825
+ };
4826
+
4827
+ // src/syncBridge.ts
4828
+ var toSyncContext = (authPrincipal) => authPrincipal ? { authPrincipal, user: authPrincipal.user } : undefined;
4829
+ var createAbsoluteAuthSyncBridge = (accessTokens) => ({
4830
+ consumeSocketTicket: async ({ audience, ticket }) => {
4831
+ const store = accessTokens.oidc.socketTicketStore;
4832
+ if (!store)
4833
+ return;
4834
+ return toSyncContext(await consumeSocketTicket({
4835
+ audience: audience ?? accessTokens.oidc.issuer,
4836
+ getUser: accessTokens.getUser,
4837
+ store,
4838
+ ticket
4839
+ }));
4840
+ },
4841
+ resolveBearer: async ({ authorization }) => toSyncContext(await resolveAccessTokenPrincipal({
4842
+ authorization,
4843
+ config: accessTokens
4844
+ }))
4845
+ });
4846
+
4778
4847
  // src/authContext.ts
4779
4848
  var createAuthContext = ({
4780
4849
  agentAuth,
@@ -4783,19 +4852,27 @@ var createAuthContext = ({
4783
4852
  authorization,
4784
4853
  emit,
4785
4854
  seedSource
4786
- }) => new Elysia8({
4787
- name: "@absolutejs/auth/context",
4788
- seed: pluginDependencySeed(seedSource)
4789
- }).use([
4790
- protectRoutePlugin({ accessTokens, authSessionStore }),
4791
- stepUpPlugin({ authSessionStore }),
4792
- authorization ? protectPermissionPlugin({
4793
- ...authorization,
4794
- authSessionStore,
4795
- emit
4796
- }) : new Elysia8,
4797
- agentAuthContextPlugin(agentAuth)
4798
- ]);
4855
+ }) => {
4856
+ const absoluteAuthSync = accessTokens ? createAbsoluteAuthSyncBridge(accessTokens) : undefined;
4857
+ const syncBridge = new Elysia8({
4858
+ name: "@absolutejs/auth/sync-bridge",
4859
+ seed: pluginDependencySeed(seedSource)
4860
+ }).decorate("absoluteAuthSync", absoluteAuthSync).as("global");
4861
+ return new Elysia8({
4862
+ name: "@absolutejs/auth/context",
4863
+ seed: pluginDependencySeed(seedSource)
4864
+ }).use([
4865
+ syncBridge,
4866
+ protectRoutePlugin({ accessTokens, authSessionStore }),
4867
+ stepUpPlugin({ authSessionStore }),
4868
+ authorization ? protectPermissionPlugin({
4869
+ ...authorization,
4870
+ authSessionStore,
4871
+ emit
4872
+ }) : new Elysia8,
4873
+ agentAuthContextPlugin(agentAuth)
4874
+ ]);
4875
+ };
4799
4876
 
4800
4877
  // src/compliance/routes.ts
4801
4878
  import { Elysia as Elysia9, t as t6 } from "elysia";
@@ -8410,57 +8487,6 @@ var updateRegisteredClient = async ({
8410
8487
 
8411
8488
  // src/oidc/socketTicketRoutes.ts
8412
8489
  import { Elysia as Elysia22, t as t15 } from "elysia";
8413
-
8414
- // src/oidc/socketTickets.ts
8415
- init_crypto();
8416
- var DEFAULT_SOCKET_TICKET_TTL_MS = 30000;
8417
- var TICKET_BYTES = 32;
8418
- var consumeSocketTicket = async ({
8419
- audience,
8420
- getUser,
8421
- now = Date.now(),
8422
- store,
8423
- ticket
8424
- }) => {
8425
- const record = await store.consumeTicket(await hashToken(ticket), now);
8426
- if (!record || record.audience !== audience)
8427
- return;
8428
- const user = await getUser(record.subject);
8429
- if (user === null)
8430
- return;
8431
- return {
8432
- audience: record.audience,
8433
- clientId: record.clientId,
8434
- kind: "access-token",
8435
- scopes: [...record.scopes],
8436
- subject: record.subject,
8437
- user
8438
- };
8439
- };
8440
- var issueSocketTicket = async ({
8441
- audience,
8442
- clientId,
8443
- now = Date.now(),
8444
- scopes,
8445
- store,
8446
- subject,
8447
- ttlMs = DEFAULT_SOCKET_TICKET_TTL_MS
8448
- }) => {
8449
- if (!Number.isFinite(ttlMs) || ttlMs <= 0)
8450
- throw new Error("socketTicketTtlMs must be positive");
8451
- const ticket = `ast_${generateSecureToken(TICKET_BYTES)}`;
8452
- await store.saveTicket({
8453
- audience,
8454
- clientId,
8455
- expiresAt: now + ttlMs,
8456
- scopes: [...scopes],
8457
- subject,
8458
- ticketHash: await hashToken(ticket)
8459
- });
8460
- return { expiresInMs: ttlMs, ticket };
8461
- };
8462
-
8463
- // src/oidc/socketTicketRoutes.ts
8464
8490
  var noStoreJson = (value, status) => new Response(JSON.stringify(value), {
8465
8491
  headers: {
8466
8492
  "cache-control": "no-store",
@@ -40636,6 +40662,7 @@ export {
40636
40662
  createAgentIdentityAssertionVerifier,
40637
40663
  createActionPipeline,
40638
40664
  createAbuseGuard,
40665
+ createAbsoluteAuthSyncBridge,
40639
40666
  consumeSocketTicket,
40640
40667
  consumePushedRequest,
40641
40668
  consumeBackupCode,
@@ -40736,5 +40763,5 @@ export {
40736
40763
  ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV
40737
40764
  };
40738
40765
 
40739
- //# debugId=D50CCD40CF8542E364756E2164756E21
40766
+ //# debugId=38465410DBFEF9EE64756E2164756E21
40740
40767
  //# sourceMappingURL=index.js.map