@hyper.authio/client 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,995 @@
1
+ import { JWK, CryptoKey } from 'jose';
2
+
3
+ /**
4
+ * Claim names Authio writes into its tokens.
5
+ */
6
+ declare const AuthioClaimTypes: {
7
+ readonly Subject: "sub";
8
+ readonly JwtId: "jti";
9
+ readonly Issuer: "iss";
10
+ readonly Audience: "aud";
11
+ readonly Expiration: "exp";
12
+ readonly IssuedAt: "iat";
13
+ readonly NotBefore: "nbf";
14
+ readonly AuthTime: "auth_time";
15
+ readonly TokenType: "typ";
16
+ readonly AuthorizedParty: "azp";
17
+ readonly Scope: "scope";
18
+ readonly SessionId: "sid";
19
+ readonly AuthenticationContextClass: "acr";
20
+ readonly AuthenticationMethods: "amr";
21
+ readonly IdentityProvider: "idp";
22
+ readonly Nonce: "nonce";
23
+ readonly OrganizationId: "org_id";
24
+ readonly OrganizationAlias: "org_alias";
25
+ readonly AccountId: "account_id";
26
+ readonly Actor: "act";
27
+ readonly DelegationId: "delegation_id";
28
+ readonly ClientId: "client_id";
29
+ readonly Name: "name";
30
+ readonly GivenName: "given_name";
31
+ readonly FamilyName: "family_name";
32
+ readonly UniqueName: "unique_name";
33
+ readonly PreferredUsername: "preferred_username";
34
+ readonly UpdatedAt: "updated_at";
35
+ readonly Email: "email";
36
+ readonly EmailVerified: "email_verified";
37
+ readonly PhoneNumber: "phone_number";
38
+ readonly PhoneNumberVerified: "phone_number_verified";
39
+ readonly ConsumerName: "consumer_name";
40
+ readonly CredentialId: "credential_id";
41
+ readonly CredentialType: "credential_type";
42
+ readonly UserResourceAccess: "user_resource_access";
43
+ readonly RealmResourceAccess: "realm_resource_access";
44
+ readonly ClientResourceAccess: "client_resource_access";
45
+ readonly PlanResourceAccess: "plan_resource_access";
46
+ readonly ConsumerResourceAccess: "consumer_resource_access";
47
+ readonly SecretResourceAccess: "secret_resource_access";
48
+ readonly SystemResourceAccess: "system_resource_access";
49
+ };
50
+ /**
51
+ * Where a role in a `*_resource_access` claim was granted.
52
+ *
53
+ * - `user`: to the person, directly or through one of their groups.
54
+ * - `realm`: to everyone who signs in to the realm.
55
+ * - `client`: to everyone who signs in through the client.
56
+ * - `plan`: by the plan of an Authio platform account (platform users only).
57
+ * - `consumer`: to a machine consumer of the client.
58
+ * - `secret`: to an account credential (API key, client secret, personal access token).
59
+ * - `system`: to an Authio platform user (the console).
60
+ */
61
+ type AuthioResourceAccessSource = "user" | "realm" | "client" | "plan" | "consumer" | "secret" | "system";
62
+ /**
63
+ * The seven `*_resource_access` claim names, mapped to their source.
64
+ */
65
+ declare const AuthioResourceAccessClaims: Readonly<Record<string, AuthioResourceAccessSource>>;
66
+ /**
67
+ * Scopes Authio defines.
68
+ */
69
+ declare const AuthioScopes: {
70
+ readonly OpenId: "openid";
71
+ readonly Profile: "profile";
72
+ readonly Email: "email";
73
+ readonly Phone: "phone";
74
+ readonly Roles: "roles";
75
+ readonly OfflineAccess: "offline_access";
76
+ };
77
+ /**
78
+ * Grant types Authio's token endpoint accepts.
79
+ */
80
+ declare const AuthioGrantTypes: {
81
+ readonly AuthorizationCode: "authorization_code";
82
+ readonly RefreshToken: "refresh_token";
83
+ readonly ClientCredentials: "client_credentials";
84
+ readonly Password: "password";
85
+ readonly DeviceCode: "urn:ietf:params:oauth:grant-type:device_code";
86
+ readonly TokenExchange: "urn:ietf:params:oauth:grant-type:token-exchange";
87
+ readonly PersonalAccessToken: "personal_access_token";
88
+ };
89
+ /**
90
+ * Token type identifiers.
91
+ */
92
+ declare const AuthioTokenTypes: {
93
+ readonly AccessTokenUrn: "urn:ietf:params:oauth:token-type:access_token";
94
+ readonly ConnectionAccessTokenUrn: "urn:authio:params:oauth:token-type:connection-access-token";
95
+ readonly AccessToken: "access_token";
96
+ readonly RefreshToken: "refresh_token";
97
+ };
98
+ /**
99
+ * OAuth error codes Authio answers with.
100
+ */
101
+ declare const AuthioOAuthErrors: {
102
+ readonly InvalidRequest: "invalid_request";
103
+ readonly InvalidClient: "invalid_client";
104
+ readonly InvalidGrant: "invalid_grant";
105
+ readonly UnauthorizedClient: "unauthorized_client";
106
+ readonly UnsupportedGrantType: "unsupported_grant_type";
107
+ readonly InvalidScope: "invalid_scope";
108
+ readonly InvalidTarget: "invalid_target";
109
+ readonly AccessDenied: "access_denied";
110
+ readonly InvalidToken: "invalid_token";
111
+ readonly AuthorizationPending: "authorization_pending";
112
+ readonly SlowDown: "slow_down";
113
+ readonly ExpiredToken: "expired_token";
114
+ readonly ConnectionRequired: "connection_required";
115
+ readonly ConnectionSelectionRequired: "connection_selection_required";
116
+ readonly ConnectionPolicyViolation: "connection_policy_violation";
117
+ readonly ServerError: "server_error";
118
+ readonly TemporarilyUnavailable: "temporarily_unavailable";
119
+ };
120
+ /**
121
+ * Webhook event types.
122
+ */
123
+ declare const AuthioWebhookEventTypes: {
124
+ readonly UserCreated: "user_created";
125
+ readonly UserUpdated: "user_updated";
126
+ readonly UserDeleted: "user_deleted";
127
+ readonly LoginSucceeded: "login_succeeded";
128
+ readonly LoginFailed: "login_failed";
129
+ readonly UserLockedOut: "user_locked_out";
130
+ readonly TokenRevoked: "token_revoked";
131
+ readonly KeysRotated: "keys_rotated";
132
+ readonly TokenReuseDetected: "token_reuse_detected";
133
+ readonly AdminResourceCreated: "admin_resource_created";
134
+ readonly AdminResourceUpdated: "admin_resource_updated";
135
+ readonly AdminResourceDeleted: "admin_resource_deleted";
136
+ readonly UserSuspended: "user_suspended";
137
+ readonly UserSuspensionEnded: "user_suspension_ended";
138
+ readonly Ping: "ping";
139
+ };
140
+ /**
141
+ * Headers Authio sends with a webhook delivery.
142
+ */
143
+ declare const AuthioWebhookHeaders: {
144
+ readonly Signature: "X-Authio-Signature";
145
+ readonly Event: "X-Authio-Event";
146
+ readonly EventId: "X-Authio-Event-Id";
147
+ };
148
+ /**
149
+ * Asymmetric signing algorithms Authio issues tokens with and accepts in client assertions.
150
+ */
151
+ declare const AuthioAsymmetricAlgorithms: readonly ["RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512"];
152
+ /**
153
+ * Defaults shared by every Authio SDK.
154
+ */
155
+ declare const AuthioDefaults: {
156
+ readonly DiscoveryPath: "/.well-known/openid-configuration";
157
+ readonly RedactedValue: "[redacted]";
158
+ readonly PlatformRealm: "authio";
159
+ readonly PlatformClientId: "authio";
160
+ readonly ApiKeyPrefix: "ak_";
161
+ readonly ClientSecretPrefix: "cs_";
162
+ readonly PersonalAccessTokenPrefix: "pat_";
163
+ /** Seconds. */
164
+ readonly ClientAssertionLifetime: 120;
165
+ /** Seconds. */
166
+ readonly MaxClientAssertionLifetime: 3600;
167
+ /** Seconds. */
168
+ readonly DeviceInterval: 5;
169
+ /** Seconds. */
170
+ readonly DeviceSlowDownIncrement: 5;
171
+ /** Seconds a token without `expires_in` is assumed to live. */
172
+ readonly AssumedTokenLifetime: 300;
173
+ /** Seconds. */
174
+ readonly DiscoveryCacheDuration: 3600;
175
+ /** Seconds. */
176
+ readonly HttpTimeout: 30;
177
+ /** Seconds. */
178
+ readonly TokenRefreshSkew: 60;
179
+ /** Seconds. */
180
+ readonly WebhookTolerance: 300;
181
+ /** Smallest RSA key Authio verifies a client assertion from, in bits. */
182
+ readonly MinimumRsaKeySize: 2048;
183
+ readonly CredentialHeaders: readonly ["authorization", "proxy-authorization", "x-api-key", "cookie", "set-cookie"];
184
+ };
185
+
186
+ /**
187
+ * Base class of every error the Authio SDKs throw on purpose.
188
+ */
189
+ declare class AuthioError extends Error {
190
+ constructor(message: string, options?: {
191
+ cause?: unknown;
192
+ });
193
+ }
194
+ /**
195
+ * An OAuth error Authio answered with, or an answer the SDK could not read.
196
+ *
197
+ * `error` is the OAuth error code; `http_{status}` when the body carried none, and `invalid_response` when a success
198
+ * body could not be read.
199
+ */
200
+ declare class AuthioProtocolError extends AuthioError {
201
+ /** The OAuth error code. */
202
+ readonly error: string;
203
+ /** The OAuth error description. */
204
+ readonly errorDescription: string | undefined;
205
+ /** Authio's own error code (`error_code`), more specific than `error`. */
206
+ readonly errorCode: string | undefined;
207
+ /** The HTTP status, when the error came from a response. */
208
+ readonly status: number | undefined;
209
+ constructor(error: string, errorDescription?: string, errorCode?: string, status?: number, options?: {
210
+ cause?: unknown;
211
+ });
212
+ }
213
+ /**
214
+ * The discovery document could not be read, or names another issuer.
215
+ */
216
+ declare class AuthioDiscoveryError extends AuthioError {
217
+ }
218
+ /**
219
+ * The SDK was configured in a way it cannot work with.
220
+ */
221
+ declare class AuthioConfigurationError extends AuthioError {
222
+ }
223
+
224
+ /**
225
+ * Time as the SDK sees it. Replace it in tests to control expiry, caching and device polling.
226
+ */
227
+ interface AuthioClock {
228
+ /** Milliseconds since the epoch. */
229
+ now(): number;
230
+ /** Waits `ms` milliseconds; rejects when the signal aborts. */
231
+ sleep(ms: number, signal?: AbortSignal): Promise<void>;
232
+ }
233
+ /**
234
+ * The real clock.
235
+ */
236
+ declare const systemClock: AuthioClock;
237
+ /**
238
+ * Where Authio is and how to reach it. Shared by the client, the API verifier and the BFF.
239
+ */
240
+ interface AuthioConnectionOptions {
241
+ /**
242
+ * The realm's issuer, such as `https://auth.example.com/realms/acme`. When absent it is composed from
243
+ * `authority` and `realm`.
244
+ */
245
+ issuer?: string;
246
+ /** Authio's base URL, such as `https://auth.example.com`. */
247
+ authority?: string;
248
+ /** The realm name. */
249
+ realm?: string;
250
+ /**
251
+ * Refuses an `http` issuer or authority unless it is loopback. Defaults to `true`; turn it off only in
252
+ * development.
253
+ */
254
+ requireHttps?: boolean;
255
+ /** Seconds the discovery document is kept. Defaults to 3600. */
256
+ discoveryCacheDuration?: number;
257
+ /** Seconds every HTTP call may take. Defaults to 30. */
258
+ httpTimeout?: number;
259
+ /** The `fetch` every call goes through. Defaults to the global one. */
260
+ fetch?: typeof fetch;
261
+ /** The clock. Defaults to the system clock. */
262
+ clock?: AuthioClock;
263
+ }
264
+ /**
265
+ * How the client authenticates to the token, introspection, revocation and device endpoints.
266
+ */
267
+ type AuthioClientAuthentication = "client_secret_basic" | "client_secret_post" | "private_key_jwt" | "none";
268
+ /**
269
+ * The connection settings, resolved once.
270
+ */
271
+ interface AuthioConnection {
272
+ readonly issuer: string;
273
+ readonly discoveryUrl: string;
274
+ readonly requireHttps: boolean;
275
+ readonly discoveryCacheDurationMs: number;
276
+ readonly httpTimeoutMs: number;
277
+ readonly fetch: typeof fetch;
278
+ readonly clock: AuthioClock;
279
+ }
280
+ /**
281
+ * Resolves and validates the connection settings.
282
+ *
283
+ * @throws AuthioConfigurationError when the issuer cannot be composed or is not HTTPS.
284
+ */
285
+ declare function resolveConnection(options: AuthioConnectionOptions): AuthioConnection;
286
+ /**
287
+ * The issuer: `issuer` when set, else `{authority}/realms/{realm}`.
288
+ *
289
+ * @throws AuthioConfigurationError when neither is configured.
290
+ */
291
+ declare function resolveIssuer(options: Pick<AuthioConnectionOptions, "issuer" | "authority" | "realm">): string;
292
+ /**
293
+ * Whether a URL may be used to reach Authio: HTTPS, or HTTP on loopback (or anywhere when HTTPS is not required).
294
+ */
295
+ declare function isAllowedUrl(value: string, requireHttps: boolean): boolean;
296
+ /**
297
+ * Percent-encodes everything but RFC 3986 unreserved characters, as .NET's `Uri.EscapeDataString` does.
298
+ */
299
+ declare function escapeDataString(value: string): string;
300
+ /**
301
+ * Converts optional seconds to milliseconds, refusing negative or non-finite values.
302
+ *
303
+ * @internal
304
+ */
305
+ declare function seconds(value: number | undefined, fallback: number, name: string): number;
306
+
307
+ /**
308
+ * The realm's OpenID Connect discovery document. Members not listed are kept as sent.
309
+ */
310
+ interface AuthioDiscoveryDocument {
311
+ issuer: string;
312
+ authorization_endpoint?: string;
313
+ token_endpoint?: string;
314
+ userinfo_endpoint?: string;
315
+ jwks_uri?: string;
316
+ introspection_endpoint?: string;
317
+ revocation_endpoint?: string;
318
+ end_session_endpoint?: string;
319
+ device_authorization_endpoint?: string;
320
+ pushed_authorization_request_endpoint?: string;
321
+ scopes_supported?: string[];
322
+ response_types_supported?: string[];
323
+ response_modes_supported?: string[];
324
+ grant_types_supported?: string[];
325
+ subject_types_supported?: string[];
326
+ id_token_signing_alg_values_supported?: string[];
327
+ token_endpoint_auth_methods_supported?: string[];
328
+ token_endpoint_auth_signing_alg_values_supported?: string[];
329
+ introspection_endpoint_auth_methods_supported?: string[];
330
+ revocation_endpoint_auth_methods_supported?: string[];
331
+ code_challenge_methods_supported?: string[];
332
+ claims_supported?: string[];
333
+ prompt_values_supported?: string[];
334
+ authorization_response_iss_parameter_supported?: boolean;
335
+ [member: string]: unknown;
336
+ }
337
+ /**
338
+ * Reads and caches the discovery document.
339
+ */
340
+ interface AuthioDiscoveryClient {
341
+ /** The connection settings the client was built with. */
342
+ readonly connection: AuthioConnection;
343
+ /**
344
+ * The document, read at most once per cache period (concurrent callers share one read).
345
+ *
346
+ * @throws AuthioDiscoveryError when it cannot be read or names another issuer.
347
+ */
348
+ get(signal?: AbortSignal): Promise<AuthioDiscoveryDocument>;
349
+ /** Drops the cached document, so the next `get` reads it again. */
350
+ invalidate(): void;
351
+ }
352
+ /**
353
+ * Creates a discovery client. It needs no client credentials, so an API that only validates tokens can use it.
354
+ */
355
+ declare function createAuthioDiscoveryClient(options: AuthioConnectionOptions | AuthioConnection): AuthioDiscoveryClient;
356
+
357
+ /**
358
+ * The OAuth error body Authio answers with.
359
+ */
360
+ interface AuthioErrorResponse {
361
+ error?: string;
362
+ error_description?: string;
363
+ error_code?: string;
364
+ connect_uri?: string;
365
+ connection_provider?: string;
366
+ connections?: {
367
+ id: string;
368
+ label?: string;
369
+ external_login?: string;
370
+ }[];
371
+ [member: string]: unknown;
372
+ }
373
+ /**
374
+ * Joins scopes into one space-separated value, splitting values that already hold several and dropping duplicates.
375
+ *
376
+ * @returns `undefined` when there is no scope.
377
+ */
378
+ declare function toScopeString(scopes: Iterable<string> | string | undefined | null): string | undefined;
379
+
380
+ /**
381
+ * A private key as the SDK accepts it: PEM text (PKCS#8, PKCS#1 RSA or SEC1 EC; PKCS#1 and SEC1 need Node), a JWK
382
+ * (object or JSON text), or a `CryptoKey`.
383
+ */
384
+ type AuthioPrivateKeyInput = string | JWK | CryptoKey;
385
+ /**
386
+ * The algorithms a client assertion may be signed with.
387
+ */
388
+ declare const AuthioClientAssertionAlgorithms: readonly ["RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512"];
389
+
390
+ /**
391
+ * How the client proves who it is.
392
+ */
393
+ interface AuthioClientCredentialsSettings {
394
+ /** The client id. */
395
+ clientId: string;
396
+ /** The client secret, for `client_secret_basic` and `client_secret_post`. */
397
+ clientSecret?: string;
398
+ /**
399
+ * Defaults to `private_key_jwt` when only a private key is configured, else `client_secret_basic`. A public client
400
+ * sets `none`.
401
+ */
402
+ clientAuthentication?: AuthioClientAuthentication;
403
+ /** The private key for `private_key_jwt`. */
404
+ clientPrivateKey?: AuthioPrivateKeyInput;
405
+ /** A PEM file holding the private key for `private_key_jwt` (Node only); re-read when it changes. */
406
+ clientPrivateKeyPath?: string;
407
+ /** The `kid` of the key, as registered in Authio. */
408
+ clientKeyId?: string;
409
+ /** The assertion's signing algorithm. Defaults to RS256 for RSA keys and the curve's ES algorithm for EC keys. */
410
+ clientSigningAlgorithm?: string;
411
+ /** Seconds a client assertion lives. Defaults to 120, at most 3600. */
412
+ clientAssertionLifetime?: number;
413
+ }
414
+ /**
415
+ * Builds the HTTP Basic value for a client id and secret, escaping both first as RFC 6749 §2.3.1 asks.
416
+ */
417
+ declare function toBasicAuthorization(clientId: string, clientSecret: string): string;
418
+
419
+ /**
420
+ * The client's own encryption key, the pair Authio encrypts the client's tokens and UserInfo to: the private JWK
421
+ * Authio hands over when it generates the pair (object or JSON text), or a PEM private key (PKCS#8 or PKCS#1 RSA).
422
+ */
423
+ type AuthioEncryptionKey = string | JWK;
424
+ /**
425
+ * Opens a compact JWE and returns its plaintext; a token that is not a JWE comes back unchanged.
426
+ */
427
+ type AuthioTokenDecrypter = (token: string) => Promise<string>;
428
+ /**
429
+ * The key management algorithms Authio encrypts with.
430
+ */
431
+ declare const AuthioKeyManagementAlgorithms: readonly ["RSA-OAEP", "RSA-OAEP-256"];
432
+ /**
433
+ * The content encryption algorithms Authio encrypts with.
434
+ */
435
+ declare const AuthioContentEncryptionAlgorithms: readonly ["A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"];
436
+ /**
437
+ * Whether a value is a compact JWE (five segments).
438
+ */
439
+ declare function isAuthioTokenEncrypted(token: unknown): token is string;
440
+ /**
441
+ * Creates a decrypter for the client's own encryption key. Keys are imported once per algorithm.
442
+ *
443
+ * @param key The key, or `undefined` when none is configured: an encrypted token then throws.
444
+ * @param setting The setting the key came from, named in errors.
445
+ */
446
+ declare function createAuthioTokenDecrypter(key: AuthioEncryptionKey | undefined, setting?: string): AuthioTokenDecrypter;
447
+
448
+ /**
449
+ * A token endpoint answer, as Authio sends it.
450
+ */
451
+ interface AuthioTokenResponse {
452
+ access_token: string;
453
+ token_type?: string;
454
+ /** Seconds. */
455
+ expires_in?: number;
456
+ /** Rotated on every refresh: store the new one. */
457
+ refresh_token?: string;
458
+ /** Seconds. */
459
+ refresh_expires_in?: number;
460
+ id_token?: string;
461
+ scope?: string;
462
+ session_state?: string;
463
+ issued_token_type?: string;
464
+ [member: string]: unknown;
465
+ }
466
+ /**
467
+ * An introspection answer (RFC 7662). Authio adds the token's other claims (roles, organization, claim-mapper
468
+ * claims, the user's own claims) as extra members.
469
+ */
470
+ interface AuthioIntrospectionResult {
471
+ active: boolean;
472
+ scope?: string;
473
+ client_id?: string;
474
+ username?: string;
475
+ token_type?: string;
476
+ exp?: number;
477
+ iat?: number;
478
+ nbf?: number;
479
+ sub?: string;
480
+ aud?: string | string[];
481
+ iss?: string;
482
+ jti?: string;
483
+ [member: string]: unknown;
484
+ }
485
+ /**
486
+ * A device authorization answer (RFC 8628).
487
+ */
488
+ interface AuthioDeviceAuthorization {
489
+ device_code: string;
490
+ user_code: string;
491
+ verification_uri: string;
492
+ verification_uri_complete?: string;
493
+ /** Seconds. */
494
+ expires_in: number;
495
+ /** Seconds between polls. */
496
+ interval?: number;
497
+ [member: string]: unknown;
498
+ }
499
+ /**
500
+ * What Authio's UserInfo endpoint answers: `sub` and the standard claims of the granted `profile`, `email` and `phone`
501
+ * scopes. Roles, claim-mapper claims, the user's own claims and the organization never reach it; read them from the
502
+ * access token or the ID token.
503
+ */
504
+ interface AuthioUserInfo {
505
+ sub: string;
506
+ name?: string;
507
+ given_name?: string;
508
+ family_name?: string;
509
+ preferred_username?: string;
510
+ email?: string;
511
+ email_verified?: boolean;
512
+ phone_number?: string;
513
+ phone_number_verified?: boolean;
514
+ [claim: string]: unknown;
515
+ }
516
+ /**
517
+ * A cached client-credentials token.
518
+ */
519
+ interface AuthioClientCredentialsToken {
520
+ readonly accessToken: string;
521
+ readonly tokenType: string;
522
+ /** Milliseconds since the epoch. */
523
+ readonly expiresAt: number;
524
+ /** When the cache renews it, in milliseconds since the epoch. */
525
+ readonly refreshAt: number;
526
+ readonly scope: string | undefined;
527
+ }
528
+ /**
529
+ * One of the person's connected accounts at a provider.
530
+ */
531
+ interface AuthioConnectionChoice {
532
+ id: string;
533
+ label?: string;
534
+ external_login?: string;
535
+ }
536
+ /**
537
+ * The account at the provider a connection token belongs to.
538
+ */
539
+ interface AuthioExternalAccount {
540
+ id?: string;
541
+ login?: string;
542
+ email?: string;
543
+ }
544
+ /**
545
+ * The outcome of exchanging a user's token for the token of one of their connected accounts.
546
+ */
547
+ type AuthioConnectionExchangeResult = AuthioConnectionGranted | AuthioConnectionRequired | AuthioConnectionSelectionRequired | AuthioConnectionRefused;
548
+ /**
549
+ * The provider's access token.
550
+ */
551
+ interface AuthioConnectionGranted {
552
+ readonly status: "granted";
553
+ readonly accessToken: string;
554
+ readonly provider: string;
555
+ readonly providerType?: string;
556
+ readonly connectionId?: string;
557
+ readonly tokenType?: string;
558
+ readonly issuedTokenType?: string;
559
+ readonly scope?: string;
560
+ readonly externalAccount?: AuthioExternalAccount;
561
+ /** Seconds. */
562
+ readonly expiresIn?: number;
563
+ }
564
+ /**
565
+ * The person has not connected an account at the provider yet; send them to `connectUri`.
566
+ */
567
+ interface AuthioConnectionRequired {
568
+ readonly status: "required";
569
+ readonly connectUri?: string;
570
+ readonly description: string;
571
+ }
572
+ /**
573
+ * The person has several accounts at the provider; ask again with one `connectionId`.
574
+ */
575
+ interface AuthioConnectionSelectionRequired {
576
+ readonly status: "selection_required";
577
+ readonly connections: readonly AuthioConnectionChoice[];
578
+ readonly description: string;
579
+ }
580
+ /**
581
+ * Authio refused the exchange.
582
+ */
583
+ interface AuthioConnectionRefused {
584
+ readonly status: "refused";
585
+ readonly error: string;
586
+ readonly code?: string;
587
+ readonly description: string;
588
+ readonly connectUri?: string;
589
+ }
590
+
591
+ /**
592
+ * Everything the Authio client needs: where Authio is, and the client's credentials.
593
+ */
594
+ interface AuthioClientOptions extends AuthioConnectionOptions, AuthioClientCredentialsSettings {
595
+ /**
596
+ * Seconds before expiry a cached token is renewed (capped at half its lifetime). Defaults to 60.
597
+ */
598
+ tokenRefreshSkew?: number;
599
+ /** The client's own encryption key, to read a UserInfo Authio answers encrypted. */
600
+ clientEncryptionKey?: AuthioEncryptionKey;
601
+ }
602
+ /**
603
+ * Per-call options.
604
+ */
605
+ interface AuthioCallOptions {
606
+ /** Aborts the call. */
607
+ signal?: AbortSignal;
608
+ }
609
+ /**
610
+ * The token endpoint's grants.
611
+ */
612
+ interface AuthioTokenClient {
613
+ /** `client_credentials`, optionally for a resource (RFC 8707). */
614
+ clientCredentials(options?: {
615
+ scopes?: Iterable<string> | string;
616
+ resource?: string;
617
+ } & AuthioCallOptions): Promise<AuthioTokenResponse>;
618
+ /** Redeems an authorization code. */
619
+ authorizationCode(options: {
620
+ code: string;
621
+ redirectUri: string;
622
+ codeVerifier?: string;
623
+ resource?: string;
624
+ } & AuthioCallOptions): Promise<AuthioTokenResponse>;
625
+ /** Refreshes; the answer carries the rotated refresh token, which must be stored. */
626
+ refresh(options: {
627
+ refreshToken: string;
628
+ scopes?: Iterable<string> | string;
629
+ } & AuthioCallOptions): Promise<AuthioTokenResponse>;
630
+ /** Exchanges a user's access token for one addressed to another resource (RFC 8693, on-behalf-of). */
631
+ exchange(options: {
632
+ subjectToken: string;
633
+ scopes?: Iterable<string> | string;
634
+ resource?: string;
635
+ } & AuthioCallOptions): Promise<AuthioTokenResponse>;
636
+ /**
637
+ * Exchanges a user's access token for the token of one of their connected accounts. OAuth refusals come back as
638
+ * a result, never thrown.
639
+ */
640
+ exchangeForConnection(options: {
641
+ subjectToken: string;
642
+ provider: string;
643
+ connectionId?: string;
644
+ } & AuthioCallOptions): Promise<AuthioConnectionExchangeResult>;
645
+ /** Starts the device flow (RFC 8628). */
646
+ deviceAuthorization(options?: {
647
+ scopes?: Iterable<string> | string;
648
+ } & AuthioCallOptions): Promise<AuthioDeviceAuthorization>;
649
+ /**
650
+ * Polls until the person approves: waits `interval` (default 5 s) before each poll, adds 5 s on `slow_down`, throws
651
+ * on `access_denied` and `expired_token`, and throws `expired_token` when `expires_in` elapses locally.
652
+ */
653
+ pollDevice(authorization: AuthioDeviceAuthorization | {
654
+ device_code: string;
655
+ interval?: number;
656
+ expires_in?: number;
657
+ }, options?: AuthioCallOptions): Promise<AuthioTokenResponse>;
658
+ /** The resource owner password grant, where the client allows it. */
659
+ password(options: {
660
+ username: string;
661
+ password: string;
662
+ scopes?: Iterable<string> | string;
663
+ } & AuthioCallOptions): Promise<AuthioTokenResponse>;
664
+ }
665
+ /**
666
+ * Client-credentials tokens, cached per scopes and resource.
667
+ */
668
+ interface AuthioClientCredentialsCache {
669
+ /**
670
+ * A token for the scopes and resource, renewed `tokenRefreshSkew` before expiry (at most half its lifetime);
671
+ * concurrent callers for one key share one request.
672
+ */
673
+ getToken(options?: {
674
+ scopes?: Iterable<string> | string;
675
+ resource?: string;
676
+ } & AuthioCallOptions): Promise<AuthioClientCredentialsToken>;
677
+ /** Drops the cached token; with `accessToken`, only when the cache still holds that token. */
678
+ invalidate(options?: {
679
+ scopes?: Iterable<string> | string;
680
+ resource?: string;
681
+ accessToken?: string;
682
+ }): void;
683
+ }
684
+ /**
685
+ * The Authio client.
686
+ */
687
+ interface AuthioClient {
688
+ /** The issuer. */
689
+ readonly issuer: string;
690
+ /** The client id. */
691
+ readonly clientId: string;
692
+ /** The connection settings. */
693
+ readonly connection: AuthioConnection;
694
+ /** The discovery document. */
695
+ readonly discovery: AuthioDiscoveryClient;
696
+ /** The token endpoint. */
697
+ readonly tokens: AuthioTokenClient;
698
+ /** Cached client-credentials tokens. */
699
+ readonly clientCredentials: AuthioClientCredentialsCache;
700
+ /**
701
+ * Introspects a token as this client (RFC 7662). Authio answers according to who asks: a token requested for a
702
+ * resource (RFC 8707) is active only to the client that resource server names as its introspection client.
703
+ */
704
+ introspect(token: string, options?: {
705
+ tokenTypeHint?: string;
706
+ } & AuthioCallOptions): Promise<AuthioIntrospectionResult>;
707
+ /** Revokes a token (RFC 7009). */
708
+ revoke(token: string, options?: {
709
+ tokenTypeHint?: string;
710
+ } & AuthioCallOptions): Promise<void>;
711
+ /**
712
+ * Reads UserInfo. A UserInfo answered as `application/jwt` is decrypted with `clientEncryptionKey` when it is a
713
+ * JWE, then verified against the realm's keys (`iss` the issuer, `aud` the client).
714
+ */
715
+ userInfo(accessToken: string, options?: AuthioCallOptions): Promise<AuthioUserInfo>;
716
+ /**
717
+ * A `fetch` that sends a cached client-credentials token, and on a `401` drops it and retries once.
718
+ */
719
+ clientCredentialsFetch(options?: {
720
+ scopes?: Iterable<string> | string;
721
+ resource?: string;
722
+ fetch?: typeof fetch;
723
+ }): typeof fetch;
724
+ }
725
+ /**
726
+ * Creates the Authio client.
727
+ *
728
+ * @throws AuthioConfigurationError when the settings are incomplete.
729
+ */
730
+ declare function createAuthioClient(options: AuthioClientOptions): AuthioClient;
731
+ /**
732
+ * When a token answer expires, and when a cache should renew it: `expires_in` (else 5 minutes) after `issuedAt`,
733
+ * renewed `refreshSkewMs` before that, at most half its lifetime.
734
+ */
735
+ declare function toClientCredentialsToken(response: AuthioTokenResponse, issuedAt: number, refreshSkewMs: number): AuthioClientCredentialsToken;
736
+
737
+ /**
738
+ * One role read from a `*_resource_access` claim, with the permissions it grants.
739
+ */
740
+ interface AuthioResourceAccessRole {
741
+ /** The claim the role came from. */
742
+ readonly source: AuthioResourceAccessSource;
743
+ /** The role name. */
744
+ readonly name: string;
745
+ /** Resource → methods the role allows on it. */
746
+ readonly permissions: Readonly<Record<string, readonly string[]>>;
747
+ }
748
+ /**
749
+ * The roles and permissions a token carries in its `*_resource_access` claims, merged across sources.
750
+ *
751
+ * Every comparison is case-insensitive, as Authio's own check is. When a name appears in different case, the first
752
+ * spelling read is the one listed.
753
+ */
754
+ declare class AuthioResourceAccess {
755
+ /** No role at all. */
756
+ static readonly empty: AuthioResourceAccess;
757
+ /** Every role read, in claim order, one entry per source it came from. */
758
+ readonly entries: readonly AuthioResourceAccessRole[];
759
+ /** Every distinct role name. */
760
+ readonly roles: readonly string[];
761
+ /** Resource → every method any role allows on it. */
762
+ readonly permissions: Readonly<Record<string, readonly string[]>>;
763
+ private readonly lookup;
764
+ constructor(entries: Iterable<AuthioResourceAccessRole>);
765
+ /** Whether no role was read. */
766
+ get isEmpty(): boolean;
767
+ /**
768
+ * Whether the token holds the role, from any source or only from the given ones.
769
+ */
770
+ hasRole(role: string, sources?: readonly AuthioResourceAccessSource[]): boolean;
771
+ /**
772
+ * Authio's grant rule: whether any role (from any source, or only from the given ones) allows `method` on
773
+ * `resource`.
774
+ */
775
+ grants(resource: string, method: string, sources?: readonly AuthioResourceAccessSource[]): boolean;
776
+ /**
777
+ * The roles that came from one source.
778
+ */
779
+ fromSource(source: AuthioResourceAccessSource): AuthioResourceAccessRole[];
780
+ }
781
+ /**
782
+ * The source a claim name stands for, when it is one of the seven `*_resource_access` claims.
783
+ */
784
+ declare function resourceAccessSourceOf(claimType: string | undefined | null): AuthioResourceAccessSource | undefined;
785
+ /**
786
+ * Reads the roles of every `*_resource_access` claim. Takes a JWT payload or introspection answer, or
787
+ * `[type, value]` pairs; each value may be the JSON object itself or its JSON text. Other claims are ignored.
788
+ */
789
+ declare function parseResourceAccess(claims: Readonly<Record<string, unknown>> | Iterable<readonly [string, unknown]>): AuthioResourceAccess;
790
+ /**
791
+ * Reads the roles of one claim value, as strictly as Authio does: a value that is not exactly
792
+ * `{role: {resource: [method]}}` contributes nothing at all. `null` roles, resources and methods are allowed and grant
793
+ * nothing.
794
+ */
795
+ declare function parseResourceAccessClaim(source: AuthioResourceAccessSource, value: unknown): AuthioResourceAccessRole[];
796
+
797
+ /**
798
+ * Why a webhook delivery failed verification.
799
+ */
800
+ type AuthioWebhookVerificationFailure = "missing_signature" | "malformed_signature" | "signature_mismatch" | "timestamp_outside_tolerance";
801
+ /**
802
+ * The outcome of verifying a webhook signature.
803
+ */
804
+ type AuthioWebhookVerificationResult = {
805
+ readonly valid: true;
806
+ readonly timestamp: Date;
807
+ } | {
808
+ readonly valid: false;
809
+ readonly failure: AuthioWebhookVerificationFailure;
810
+ readonly reason: string;
811
+ readonly timestamp?: Date;
812
+ };
813
+ /**
814
+ * A webhook event. `data` holds the event-specific payload; read it typed with the `as…` helpers.
815
+ */
816
+ interface AuthioWebhookEvent {
817
+ readonly id: string;
818
+ readonly type: string;
819
+ /** Seconds since the epoch. */
820
+ readonly created_at: number;
821
+ readonly realm_id?: string;
822
+ readonly client_id?: string;
823
+ readonly data: unknown;
824
+ [member: string]: unknown;
825
+ }
826
+ /** `user_created`, `user_updated`, `user_deleted`. */
827
+ interface AuthioWebhookUserData {
828
+ id: string;
829
+ username?: string;
830
+ email?: string;
831
+ first_name?: string;
832
+ last_name?: string;
833
+ email_confirmed: boolean;
834
+ status?: string;
835
+ realm_id?: string;
836
+ client_id?: string;
837
+ }
838
+ /** `login_succeeded`, `login_failed`. */
839
+ interface AuthioWebhookLoginData {
840
+ grant_type?: string;
841
+ user_id?: string;
842
+ username?: string;
843
+ email?: string;
844
+ ip_address?: string;
845
+ user_agent?: string;
846
+ session_id?: string;
847
+ failure_reason?: string;
848
+ resource?: string;
849
+ scopes?: string;
850
+ }
851
+ /** `user_locked_out`. */
852
+ interface AuthioWebhookUserLockedOutData {
853
+ user_id: string;
854
+ username?: string;
855
+ email?: string;
856
+ lockout_end?: string;
857
+ access_failed_count: number;
858
+ }
859
+ /** `token_revoked`. */
860
+ interface AuthioWebhookTokenRevokedData {
861
+ token_id?: string;
862
+ subject?: string;
863
+ session_id?: string;
864
+ token_type_hint?: string;
865
+ }
866
+ /** `keys_rotated`. */
867
+ interface AuthioWebhookKeysRotatedData {
868
+ signing_key_id?: string;
869
+ encryption_key_id?: string;
870
+ revoked_keys_count?: number;
871
+ rotation_days?: number;
872
+ automatic?: boolean;
873
+ }
874
+ /** `token_reuse_detected`. */
875
+ interface AuthioWebhookTokenReuseDetectedData {
876
+ token_id?: string;
877
+ subject?: string;
878
+ session_id?: string;
879
+ ip_address?: string;
880
+ user_agent?: string;
881
+ }
882
+ /** `admin_resource_created`, `admin_resource_updated`, `admin_resource_deleted`. */
883
+ interface AuthioWebhookAdminResourceData {
884
+ action?: string;
885
+ resource_type?: string;
886
+ resource_id?: string;
887
+ realm_id?: string;
888
+ client_id?: string;
889
+ actor_user_id?: string;
890
+ actor_username?: string;
891
+ actor_email?: string;
892
+ ip_address?: string;
893
+ method?: string;
894
+ path?: string;
895
+ }
896
+ /** `user_suspended`, `user_suspension_ended`. */
897
+ interface AuthioWebhookUserSuspensionData {
898
+ id: string;
899
+ user_id: string;
900
+ level?: string;
901
+ status?: string;
902
+ starts_at?: string;
903
+ ends_at?: string;
904
+ restricted_scopes: string[];
905
+ revokes_every_role: boolean;
906
+ revoked_role_ids: string[];
907
+ sessions_terminated_at?: string;
908
+ lifted_at?: string;
909
+ }
910
+ /** `ping`. */
911
+ interface AuthioWebhookPingData {
912
+ message?: string;
913
+ subscription?: string;
914
+ }
915
+ /**
916
+ * The data shape of each event type.
917
+ */
918
+ interface AuthioWebhookDataByType {
919
+ user_created: AuthioWebhookUserData;
920
+ user_updated: AuthioWebhookUserData;
921
+ user_deleted: AuthioWebhookUserData;
922
+ login_succeeded: AuthioWebhookLoginData;
923
+ login_failed: AuthioWebhookLoginData;
924
+ user_locked_out: AuthioWebhookUserLockedOutData;
925
+ token_revoked: AuthioWebhookTokenRevokedData;
926
+ keys_rotated: AuthioWebhookKeysRotatedData;
927
+ token_reuse_detected: AuthioWebhookTokenReuseDetectedData;
928
+ admin_resource_created: AuthioWebhookAdminResourceData;
929
+ admin_resource_updated: AuthioWebhookAdminResourceData;
930
+ admin_resource_deleted: AuthioWebhookAdminResourceData;
931
+ user_suspended: AuthioWebhookUserSuspensionData;
932
+ user_suspension_ended: AuthioWebhookUserSuspensionData;
933
+ ping: AuthioWebhookPingData;
934
+ }
935
+ /**
936
+ * An event narrowed to one type, with its data typed.
937
+ */
938
+ type AuthioTypedWebhookEvent<T extends keyof AuthioWebhookDataByType> = AuthioWebhookEvent & {
939
+ readonly type: T;
940
+ readonly data: AuthioWebhookDataByType[T];
941
+ };
942
+ /**
943
+ * Verifies the `X-Authio-Signature` header (`t={unixSeconds},v1={hex}`) against the raw body: HMAC-SHA256 of
944
+ * `{t}.{body}` with the secret, compared in constant time, any matching `v1` accepted, the signature checked before
945
+ * the timestamp.
946
+ *
947
+ * @param signatureHeader The header value.
948
+ * @param rawBody The body exactly as received.
949
+ * @param secret The webhook's secret.
950
+ * @param options `tolerance` in seconds (default 300) and `now` in milliseconds (default the current time).
951
+ */
952
+ declare function verifyWebhookSignature(signatureHeader: string | null | undefined, rawBody: string | Uint8Array, secret: string, options?: {
953
+ tolerance?: number;
954
+ now?: number;
955
+ }): Promise<AuthioWebhookVerificationResult>;
956
+ /**
957
+ * Computes the `X-Authio-Signature` value Authio would send, for tests and replays.
958
+ *
959
+ * @param timestamp Milliseconds since the epoch, or a date.
960
+ */
961
+ declare function computeWebhookSignatureHeader(rawBody: string | Uint8Array, secret: string, timestamp: number | Date): Promise<string>;
962
+ /**
963
+ * Parses a webhook body.
964
+ *
965
+ * @throws SyntaxError when it is not JSON or has no `type`.
966
+ */
967
+ declare function parseWebhookEvent(rawBody: string | Uint8Array): AuthioWebhookEvent;
968
+ /**
969
+ * Parses a webhook body, or returns `undefined` when it cannot be read.
970
+ */
971
+ declare function tryParseWebhookEvent(rawBody: string | Uint8Array | null | undefined): AuthioWebhookEvent | undefined;
972
+ /**
973
+ * Whether the event is of one of the given types, narrowing its data.
974
+ */
975
+ declare function isWebhookEventOfType<T extends keyof AuthioWebhookDataByType>(event: AuthioWebhookEvent, ...types: T[]): event is AuthioTypedWebhookEvent<T>;
976
+ /** The data of a user event, or `undefined` for any other type. */
977
+ declare const asUserEvent: (event: AuthioWebhookEvent) => AuthioWebhookUserData | undefined;
978
+ /** The data of a login event, or `undefined` for any other type. */
979
+ declare const asLoginEvent: (event: AuthioWebhookEvent) => AuthioWebhookLoginData | undefined;
980
+ /** The data of a lockout event, or `undefined` for any other type. */
981
+ declare const asUserLockedOutEvent: (event: AuthioWebhookEvent) => AuthioWebhookUserLockedOutData | undefined;
982
+ /** The data of a revocation event, or `undefined` for any other type. */
983
+ declare const asTokenRevokedEvent: (event: AuthioWebhookEvent) => AuthioWebhookTokenRevokedData | undefined;
984
+ /** The data of a key rotation event, or `undefined` for any other type. */
985
+ declare const asKeysRotatedEvent: (event: AuthioWebhookEvent) => AuthioWebhookKeysRotatedData | undefined;
986
+ /** The data of a refresh token reuse event, or `undefined` for any other type. */
987
+ declare const asTokenReuseDetectedEvent: (event: AuthioWebhookEvent) => AuthioWebhookTokenReuseDetectedData | undefined;
988
+ /** The data of an admin resource event, or `undefined` for any other type. */
989
+ declare const asAdminResourceEvent: (event: AuthioWebhookEvent) => AuthioWebhookAdminResourceData | undefined;
990
+ /** The data of a suspension event, or `undefined` for any other type. */
991
+ declare const asUserSuspensionEvent: (event: AuthioWebhookEvent) => AuthioWebhookUserSuspensionData | undefined;
992
+ /** The data of a ping, or `undefined` for any other type. */
993
+ declare const asPingEvent: (event: AuthioWebhookEvent) => AuthioWebhookPingData | undefined;
994
+
995
+ export { AuthioAsymmetricAlgorithms, type AuthioCallOptions, AuthioClaimTypes, type AuthioClient, AuthioClientAssertionAlgorithms, type AuthioClientAuthentication, type AuthioClientCredentialsCache, type AuthioClientCredentialsSettings, type AuthioClientCredentialsToken, type AuthioClientOptions, type AuthioClock, AuthioConfigurationError, type AuthioConnection, type AuthioConnectionChoice, type AuthioConnectionExchangeResult, type AuthioConnectionGranted, type AuthioConnectionOptions, type AuthioConnectionRefused, type AuthioConnectionRequired, type AuthioConnectionSelectionRequired, AuthioContentEncryptionAlgorithms, AuthioDefaults, type AuthioDeviceAuthorization, type AuthioDiscoveryClient, type AuthioDiscoveryDocument, AuthioDiscoveryError, type AuthioEncryptionKey, AuthioError, type AuthioErrorResponse, type AuthioExternalAccount, AuthioGrantTypes, type AuthioIntrospectionResult, AuthioKeyManagementAlgorithms, AuthioOAuthErrors, type AuthioPrivateKeyInput, AuthioProtocolError, AuthioResourceAccess, AuthioResourceAccessClaims, type AuthioResourceAccessRole, type AuthioResourceAccessSource, AuthioScopes, type AuthioTokenClient, type AuthioTokenDecrypter, type AuthioTokenResponse, AuthioTokenTypes, type AuthioTypedWebhookEvent, type AuthioUserInfo, type AuthioWebhookAdminResourceData, type AuthioWebhookDataByType, type AuthioWebhookEvent, AuthioWebhookEventTypes, AuthioWebhookHeaders, type AuthioWebhookKeysRotatedData, type AuthioWebhookLoginData, type AuthioWebhookPingData, type AuthioWebhookTokenReuseDetectedData, type AuthioWebhookTokenRevokedData, type AuthioWebhookUserData, type AuthioWebhookUserLockedOutData, type AuthioWebhookUserSuspensionData, type AuthioWebhookVerificationFailure, type AuthioWebhookVerificationResult, asAdminResourceEvent, asKeysRotatedEvent, asLoginEvent, asPingEvent, asTokenReuseDetectedEvent, asTokenRevokedEvent, asUserEvent, asUserLockedOutEvent, asUserSuspensionEvent, computeWebhookSignatureHeader, createAuthioClient, createAuthioDiscoveryClient, createAuthioTokenDecrypter, escapeDataString, isAllowedUrl, isAuthioTokenEncrypted, isWebhookEventOfType, parseResourceAccess, parseResourceAccessClaim, parseWebhookEvent, resolveConnection, resolveIssuer, resourceAccessSourceOf, seconds, systemClock, toBasicAuthorization, toClientCredentialsToken, toScopeString, tryParseWebhookEvent, verifyWebhookSignature };