@hyper.authio/server 0.1.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -7
- package/dist/index.cjs +270 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +165 -16
- package/dist/index.d.ts +165 -16
- package/dist/index.js +267 -98
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthioResourceAccess, AuthioResourceAccessSource, AuthioError, AuthioConnection, AuthioDiscoveryClient, AuthioClient, AuthioConnectionOptions, AuthioClientOptions,
|
|
1
|
+
import { AuthioCallerKind, AuthioCredentialForm, AuthioResourceAccess, AuthioIntrospectionResult, AuthioResourceAccessSource, AuthioClock, AuthioError, AuthioTokenFailure, AuthioConnection, AuthioDiscoveryClient, AuthioClient, AuthioConnectionOptions, AuthioClientOptions, AuthioEncryptionKeySource, AuthioWebhookEvent, AuthioWebhookDataByType, AuthioTypedWebhookEvent, AuthioClientCredentialsToken } from '@hyper.authio/client';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The party acting for the subject, from the `act` claim (RFC 8693): who exchanged the token, nested when the chain
|
|
@@ -7,8 +7,17 @@ import { AuthioResourceAccess, AuthioResourceAccessSource, AuthioError, AuthioCo
|
|
|
7
7
|
interface AuthioActor {
|
|
8
8
|
readonly clientId: string | undefined;
|
|
9
9
|
readonly subject: string | undefined;
|
|
10
|
+
/** `name`, on an impersonation: the administrator's display name. */
|
|
11
|
+
readonly name: string | undefined;
|
|
10
12
|
readonly actor: AuthioActor | undefined;
|
|
11
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* The administrator who impersonates the subject (an `act` with `sub` and no `client_id`).
|
|
16
|
+
*/
|
|
17
|
+
interface AuthioImpersonator {
|
|
18
|
+
readonly subject: string;
|
|
19
|
+
readonly name: string | undefined;
|
|
20
|
+
}
|
|
12
21
|
/**
|
|
13
22
|
* Where the user reads flat (non-`*_resource_access`) roles and groups from.
|
|
14
23
|
*/
|
|
@@ -31,6 +40,41 @@ interface AuthioUserClaimSettings {
|
|
|
31
40
|
declare class AuthioUser {
|
|
32
41
|
/** `sub`: the person's id, or the credential's for a machine caller. */
|
|
33
42
|
readonly subject: string;
|
|
43
|
+
/**
|
|
44
|
+
* Who called: `user` (a person signed in), `client` (a client as itself), `consumer` (a machine consumer of a
|
|
45
|
+
* client) or `account_credential` (a credential of an Authio account).
|
|
46
|
+
*/
|
|
47
|
+
readonly kind: AuthioCallerKind;
|
|
48
|
+
/**
|
|
49
|
+
* How a machine caller proved who it is (`client_secret`, `personal_access_token`, `api_key`,
|
|
50
|
+
* `consumer_api_key`); `undefined` for a person or a client.
|
|
51
|
+
*/
|
|
52
|
+
readonly credentialForm: AuthioCredentialForm | undefined;
|
|
53
|
+
/** `consumer_name`, for a consumer. */
|
|
54
|
+
readonly consumerName: string | undefined;
|
|
55
|
+
/** `credential_name`, for an account credential. */
|
|
56
|
+
readonly credentialName: string | undefined;
|
|
57
|
+
/** `owner_user_id`: the person who made the credential. */
|
|
58
|
+
readonly ownerUserId: string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* `owner_username`: the person who made the credential. On an account credential Authio wrote it to
|
|
61
|
+
* `consumer_name` before, which is read when `owner_username` is absent.
|
|
62
|
+
*/
|
|
63
|
+
readonly ownerUsername: string | undefined;
|
|
64
|
+
/** `credential_realm`: the one realm an account credential is limited to. */
|
|
65
|
+
readonly credentialRealm: string | undefined;
|
|
66
|
+
/** `credential_client`: the one client an account credential is limited to. */
|
|
67
|
+
readonly credentialClient: string | undefined;
|
|
68
|
+
/** Whether an administrator impersonates the subject. */
|
|
69
|
+
readonly impersonated: boolean;
|
|
70
|
+
/** The administrator impersonating the subject. */
|
|
71
|
+
readonly impersonator: AuthioImpersonator | undefined;
|
|
72
|
+
/** Whether a client acts for the subject through a delegation (`act` with `client_id`). */
|
|
73
|
+
readonly delegated: boolean;
|
|
74
|
+
/** The clients acting for the subject, outermost first. */
|
|
75
|
+
readonly actorChain: readonly string[];
|
|
76
|
+
/** `auth_time`, in seconds since the epoch. */
|
|
77
|
+
readonly authTime: number | undefined;
|
|
34
78
|
/** The client the token was issued to (`azp`, else `client_id`). */
|
|
35
79
|
readonly clientId: string | undefined;
|
|
36
80
|
/** `sid`. */
|
|
@@ -86,10 +130,16 @@ declare class AuthioUser {
|
|
|
86
130
|
* @param claims The token's payload, or the introspection answer's members.
|
|
87
131
|
* @param settings Where flat roles and groups are read from.
|
|
88
132
|
* @param token The access token, kept for forwarding and on-behalf-of.
|
|
133
|
+
* @param source Where the claims come from: a JWT (default) or an introspection answer. An introspection answer for
|
|
134
|
+
* a consumer that reports no `exp` and no `actor_type` is the consumer's API key (Authio reports no lifetime for a
|
|
135
|
+
* key), so its `credentialForm` is `consumer_api_key`.
|
|
136
|
+
*/
|
|
137
|
+
constructor(claims: Readonly<Record<string, unknown>>, settings?: AuthioUserClaimSettings, token?: string, source?: "token" | "introspection");
|
|
138
|
+
/**
|
|
139
|
+
* Reads the caller from an introspection answer: `client_id` becomes `azp`, `username` becomes
|
|
140
|
+
* `preferred_username`, and `token_type` becomes `typ` unless it is `api_key` (a consumer's API key).
|
|
89
141
|
*/
|
|
90
|
-
|
|
91
|
-
/** Whether an actor exchanged the token on the subject's behalf. */
|
|
92
|
-
get isDelegated(): boolean;
|
|
142
|
+
static fromIntrospection(result: AuthioIntrospectionResult, settings?: AuthioUserClaimSettings, token?: string): AuthioUser;
|
|
93
143
|
/** Whether the scope was granted. */
|
|
94
144
|
hasScope(scope: string): boolean;
|
|
95
145
|
/**
|
|
@@ -138,6 +188,10 @@ interface AuthioRuleFailure {
|
|
|
138
188
|
readonly error?: "insufficient_scope" | "insufficient_user_authentication";
|
|
139
189
|
/** The required scopes, for `insufficient_scope`. */
|
|
140
190
|
readonly scope?: string;
|
|
191
|
+
/** The context classes to ask for again, for `insufficient_user_authentication` (RFC 9470 `acr_values`). */
|
|
192
|
+
readonly acrValues?: string;
|
|
193
|
+
/** How old the sign-in may be, in seconds, for `insufficient_user_authentication` (RFC 9470 `max_age`). */
|
|
194
|
+
readonly maxAge?: number;
|
|
141
195
|
}
|
|
142
196
|
/**
|
|
143
197
|
* A condition on the caller.
|
|
@@ -150,7 +204,8 @@ interface AuthioRule {
|
|
|
150
204
|
}
|
|
151
205
|
/**
|
|
152
206
|
* Checks every rule. On refusal the message joins every rule's, and the error is the one asking for a stronger
|
|
153
|
-
* sign-in, else the first one
|
|
207
|
+
* sign-in (with the strongest `acr_values` and the shortest `max_age` the failing rules ask for), else the first one
|
|
208
|
+
* that has an error.
|
|
154
209
|
*/
|
|
155
210
|
declare function authorize(user: AuthioUser, ...rules: AuthioRule[]): AuthioRuleFailure | undefined;
|
|
156
211
|
/**
|
|
@@ -184,13 +239,30 @@ declare function requireClaim(type: string, ...values: string[]): AuthioRule;
|
|
|
184
239
|
*/
|
|
185
240
|
declare function requireOrganization(organization?: string): AuthioRule;
|
|
186
241
|
/**
|
|
187
|
-
* Requires a minimum authentication level (`acr`): 1 one factor, 2 several, 3 one of them phishing-resistant.
|
|
242
|
+
* Requires a minimum authentication level (`acr`): 1 one factor, 2 several, 3 one of them phishing-resistant. The
|
|
243
|
+
* refusal asks for that level again (`acr_values`), and for a sign-in at most `maxAge` seconds old when given.
|
|
244
|
+
*/
|
|
245
|
+
declare function requireAuthenticationLevel(minimumLevel: number, options?: {
|
|
246
|
+
maxAge?: number;
|
|
247
|
+
clock?: AuthioClock;
|
|
248
|
+
}): AuthioRule;
|
|
249
|
+
/**
|
|
250
|
+
* Requires authentication methods (`amr`, case-insensitive), such as `otp`, `swk` or `fed`. The refusal asks for the
|
|
251
|
+
* context class the methods imply (`2` for `mfa`/`otp`/`mca`, `3` for `swk`/`hwk`), or for `acrValues` when given.
|
|
252
|
+
*/
|
|
253
|
+
declare function requireAuthenticationMethod(methods: string | readonly string[], match?: AuthioMatch, options?: {
|
|
254
|
+
acrValues?: string;
|
|
255
|
+
}): AuthioRule;
|
|
256
|
+
/**
|
|
257
|
+
* Requires a sign-in at most `maxAge` seconds old (`auth_time`); the refusal asks for it with `max_age` (RFC 9470).
|
|
188
258
|
*/
|
|
189
|
-
declare function
|
|
259
|
+
declare function requireRecentAuthentication(maxAge: number, options?: {
|
|
260
|
+
clock?: AuthioClock;
|
|
261
|
+
}): AuthioRule;
|
|
190
262
|
/**
|
|
191
|
-
* Requires
|
|
263
|
+
* Requires the caller to be of one of the kinds: `user`, `client`, `consumer`, `account_credential`.
|
|
192
264
|
*/
|
|
193
|
-
declare function
|
|
265
|
+
declare function requireCallerKind(kinds: AuthioCallerKind | readonly AuthioCallerKind[]): AuthioRule;
|
|
194
266
|
/**
|
|
195
267
|
* Requires the token to have been issued to one of the clients (`azp`, else `client_id`).
|
|
196
268
|
*/
|
|
@@ -213,10 +285,18 @@ declare class AuthioBearerError extends AuthioError {
|
|
|
213
285
|
readonly error: "invalid_token" | undefined;
|
|
214
286
|
/** Why the token was refused, safe to send to the caller. */
|
|
215
287
|
readonly description: string | undefined;
|
|
288
|
+
/** Why the token was refused, as a stable code; `undefined` when there was no token or Authio could not be asked. */
|
|
289
|
+
readonly reason: AuthioTokenFailure | "inactive" | "unconfirmed" | undefined;
|
|
290
|
+
/** The API's protected resource metadata URL (RFC 9728), sent as `resource_metadata` when configured. */
|
|
291
|
+
readonly resourceMetadata: string | undefined;
|
|
216
292
|
constructor(description: string | undefined, options?: {
|
|
217
293
|
error?: "invalid_token" | undefined;
|
|
218
294
|
cause?: unknown;
|
|
295
|
+
reason?: AuthioTokenFailure | "inactive" | "unconfirmed";
|
|
296
|
+
resourceMetadata?: string;
|
|
219
297
|
});
|
|
298
|
+
/** The same refusal, pointing at the API's protected resource metadata. */
|
|
299
|
+
withResourceMetadata(resourceMetadata: string | undefined): AuthioBearerError;
|
|
220
300
|
/** The `WWW-Authenticate` value. */
|
|
221
301
|
get wwwAuthenticate(): string;
|
|
222
302
|
}
|
|
@@ -231,8 +311,8 @@ declare class AuthioForbiddenError extends AuthioError {
|
|
|
231
311
|
get wwwAuthenticate(): string | undefined;
|
|
232
312
|
}
|
|
233
313
|
/**
|
|
234
|
-
* The `WWW-Authenticate` value of a refusal: `insufficient_scope` (with `scope`) or
|
|
235
|
-
* `
|
|
314
|
+
* The `WWW-Authenticate` value of a refusal: `insufficient_scope` (with `scope`) or `insufficient_user_authentication`
|
|
315
|
+
* (with `acr_values` and `max_age`, RFC 9470).
|
|
236
316
|
*/
|
|
237
317
|
declare function toForbiddenChallenge(failure: AuthioRuleFailure): string | undefined;
|
|
238
318
|
/**
|
|
@@ -246,15 +326,27 @@ declare function toProblemDetails(error: AuthioBearerError | AuthioForbiddenErro
|
|
|
246
326
|
* - `none`: the JWT is validated locally (signature, issuer, audience, lifetime). Fastest; a revoked token stays
|
|
247
327
|
* valid until it expires.
|
|
248
328
|
* - `activeCheck`: validated locally, then confirmed active by introspection (cached per `jti`).
|
|
249
|
-
* - `introspectionOnly`: introspection alone, for opaque (reference) or encrypted
|
|
329
|
+
* - `introspectionOnly`: introspection alone, for opaque (reference) tokens, or encrypted ones without the key.
|
|
250
330
|
*/
|
|
251
331
|
type AuthioIntrospectionMode = "none" | "activeCheck" | "introspectionOnly";
|
|
252
332
|
/**
|
|
253
333
|
* How an API validates Authio access tokens.
|
|
254
334
|
*/
|
|
255
335
|
interface AuthioVerifierOptions extends AuthioConnectionOptions, AuthioUserClaimSettings {
|
|
256
|
-
/** The audiences this API accepts: its resource identifier (RFC 8707) or client id. Required. */
|
|
257
|
-
audiences
|
|
336
|
+
/** The audiences this API accepts: its resource identifier (RFC 8707) or client id. Required unless `resource` is set. */
|
|
337
|
+
audiences?: string | readonly string[];
|
|
338
|
+
/**
|
|
339
|
+
* The API's own resource identifier (RFC 8707), such as `https://orders.example.com`. Added to `audiences`, and
|
|
340
|
+
* the `resource` of its protected resource metadata (RFC 9728).
|
|
341
|
+
*/
|
|
342
|
+
resource?: string;
|
|
343
|
+
/**
|
|
344
|
+
* Points `401` challenges at the API's protected resource metadata (RFC 9728) with `resource_metadata`: `true`
|
|
345
|
+
* for `{origin of resource}/.well-known/oauth-protected-resource{path of resource}`, or the URL itself. Off by default.
|
|
346
|
+
*/
|
|
347
|
+
resourceMetadata?: boolean | string;
|
|
348
|
+
/** Scopes every request must carry (all of them); `authioBearer` answers `403 insufficient_scope` otherwise. */
|
|
349
|
+
requiredScopes?: readonly string[];
|
|
258
350
|
/** Defaults to `none`. */
|
|
259
351
|
introspection?: AuthioIntrospectionMode;
|
|
260
352
|
/**
|
|
@@ -271,6 +363,15 @@ interface AuthioVerifierOptions extends AuthioConnectionOptions, AuthioUserClaim
|
|
|
271
363
|
validAlgorithms?: readonly string[];
|
|
272
364
|
/** Refuses a token whose `typ` claim is present and not `Bearer` (an ID token, for one). Defaults to `true`. */
|
|
273
365
|
rejectNonAccessTokens?: boolean;
|
|
366
|
+
/**
|
|
367
|
+
* The private half of the encryption key Authio encrypts this API's access tokens to (the resource server's or its
|
|
368
|
+
* client's), so encrypted tokens are decrypted and validated locally (RSA-OAEP, RSA-OAEP-256).
|
|
369
|
+
*/
|
|
370
|
+
clientEncryptionKey?: AuthioEncryptionKeySource;
|
|
371
|
+
/** A PEM or JWK file holding `clientEncryptionKey` (Node only). */
|
|
372
|
+
clientEncryptionKeyPath?: string;
|
|
373
|
+
/** Accepted for parity with the other Authio SDKs; RSA1_5 stays refused, because Node cannot decrypt it. */
|
|
374
|
+
allowLegacyEncryptionAlgorithms?: boolean;
|
|
274
375
|
}
|
|
275
376
|
/**
|
|
276
377
|
* Validates Authio access tokens and reads the caller.
|
|
@@ -282,6 +383,12 @@ interface AuthioVerifier {
|
|
|
282
383
|
readonly discovery: AuthioDiscoveryClient;
|
|
283
384
|
/** The accepted audiences. */
|
|
284
385
|
readonly audiences: readonly string[];
|
|
386
|
+
/** The API's resource identifier, when configured. */
|
|
387
|
+
readonly resource: string | undefined;
|
|
388
|
+
/** The protected resource metadata URL sent in challenges, when turned on. */
|
|
389
|
+
readonly resourceMetadataUrl: string | undefined;
|
|
390
|
+
/** Scopes every request must carry. */
|
|
391
|
+
readonly requiredScopes: readonly string[];
|
|
285
392
|
/** The introspection mode. */
|
|
286
393
|
readonly introspection: AuthioIntrospectionMode;
|
|
287
394
|
/** The client used for introspection, when there is one. */
|
|
@@ -307,7 +414,7 @@ declare const AuthioBearerErrorDescriptions: {
|
|
|
307
414
|
readonly Inactive: "Authio reports the token as not active to this API's client. It was revoked or has expired or its session ended; or this API's client is not the introspection client of the resource server the token is for.";
|
|
308
415
|
readonly Unconfirmed: "Authio could not be reached to confirm that the token is active.";
|
|
309
416
|
readonly Empty: "The token is empty.";
|
|
310
|
-
readonly Encrypted: "The token is encrypted; validate it with introspection ('introspectionOnly').";
|
|
417
|
+
readonly Encrypted: "The token is encrypted; set clientEncryptionKey to decrypt it, or validate it with introspection ('introspectionOnly').";
|
|
311
418
|
readonly SigningKeysUnavailable: "Authio could not be reached to read its signing keys.";
|
|
312
419
|
};
|
|
313
420
|
/**
|
|
@@ -321,6 +428,48 @@ declare function createAuthioVerifier(options: AuthioVerifierOptions): AuthioVer
|
|
|
321
428
|
*/
|
|
322
429
|
declare function readBearerToken(header: string | null | undefined): string | undefined;
|
|
323
430
|
|
|
431
|
+
/**
|
|
432
|
+
* What an API publishes about itself as a protected resource (RFC 9728).
|
|
433
|
+
*/
|
|
434
|
+
interface AuthioProtectedResourceMetadataOptions extends Pick<AuthioConnectionOptions, "issuer" | "authority" | "realm"> {
|
|
435
|
+
/** The API's resource identifier (RFC 8707), such as `https://orders.example.com/api`. Required. */
|
|
436
|
+
resource: string;
|
|
437
|
+
/** Scopes a client can ask for to call the API. */
|
|
438
|
+
scopesSupported?: readonly string[];
|
|
439
|
+
/** A name to show to people. */
|
|
440
|
+
resourceName?: string;
|
|
441
|
+
/** A page documenting the API. */
|
|
442
|
+
resourceDocumentation?: string;
|
|
443
|
+
/** Further members, sent as given. */
|
|
444
|
+
extra?: Record<string, unknown>;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* The protected resource metadata document (RFC 9728 §2).
|
|
448
|
+
*/
|
|
449
|
+
interface AuthioProtectedResourceMetadata {
|
|
450
|
+
resource: string;
|
|
451
|
+
authorization_servers: string[];
|
|
452
|
+
bearer_methods_supported: string[];
|
|
453
|
+
scopes_supported?: string[];
|
|
454
|
+
resource_name?: string;
|
|
455
|
+
resource_documentation?: string;
|
|
456
|
+
[member: string]: unknown;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Where a resource's metadata is published: `{origin}/.well-known/oauth-protected-resource{path}` (RFC 9728 §3.1),
|
|
460
|
+
* the path being the resource's own, without a trailing slash.
|
|
461
|
+
*/
|
|
462
|
+
declare function protectedResourceMetadataUrl(resource: string): string;
|
|
463
|
+
/**
|
|
464
|
+
* The path a resource's metadata is served at on the API itself: `/.well-known/oauth-protected-resource{path}`.
|
|
465
|
+
*/
|
|
466
|
+
declare function protectedResourceMetadataPath(resource: string): string;
|
|
467
|
+
/**
|
|
468
|
+
* Builds the API's protected resource metadata: the resource, the realm's issuer as its authorization server, bearer
|
|
469
|
+
* tokens in the `Authorization` header, and the optional scopes, name and documentation.
|
|
470
|
+
*/
|
|
471
|
+
declare function createProtectedResourceMetadata(options: AuthioProtectedResourceMetadataOptions): AuthioProtectedResourceMetadata;
|
|
472
|
+
|
|
324
473
|
/**
|
|
325
474
|
* Remembers delivered event ids, so a redelivery is acknowledged without running the handlers twice.
|
|
326
475
|
*/
|
|
@@ -436,4 +585,4 @@ declare function createOnBehalfOf(options: {
|
|
|
436
585
|
tokenRefreshSkew?: number;
|
|
437
586
|
}): AuthioOnBehalfOf;
|
|
438
587
|
|
|
439
|
-
export { type AuthioActor, AuthioBearerError, AuthioBearerErrorDescriptions, type AuthioDownstreamSubject, AuthioForbiddenError, type AuthioIntrospectionMode, type AuthioMatch, type AuthioOnBehalfOf, type AuthioRule, type AuthioRuleFailure, AuthioUser, type AuthioUserClaimSettings, type AuthioVerifier, type AuthioVerifierOptions, type AuthioWebhookDeduplicationStore, type AuthioWebhookHandler, type AuthioWebhookOptions, type AuthioWebhookOutcome, type AuthioWebhooks, allOf, anyOf, authorize, createAuthioVerifier, createAuthioWebhooks, createForwardingFetch, createMemoryDeduplicationStore, createOnBehalfOf, readBearerToken, requireAuthenticationLevel, requireAuthenticationMethod, requireClaim, requireClient, requireGroup, requireOrganization, requirePermission, requireRole, requireScope, toForbiddenChallenge, toProblemDetails };
|
|
588
|
+
export { type AuthioActor, AuthioBearerError, AuthioBearerErrorDescriptions, type AuthioDownstreamSubject, AuthioForbiddenError, type AuthioImpersonator, type AuthioIntrospectionMode, type AuthioMatch, type AuthioOnBehalfOf, type AuthioProtectedResourceMetadata, type AuthioProtectedResourceMetadataOptions, type AuthioRule, type AuthioRuleFailure, AuthioUser, type AuthioUserClaimSettings, type AuthioVerifier, type AuthioVerifierOptions, type AuthioWebhookDeduplicationStore, type AuthioWebhookHandler, type AuthioWebhookOptions, type AuthioWebhookOutcome, type AuthioWebhooks, allOf, anyOf, authorize, createAuthioVerifier, createAuthioWebhooks, createForwardingFetch, createMemoryDeduplicationStore, createOnBehalfOf, createProtectedResourceMetadata, protectedResourceMetadataPath, protectedResourceMetadataUrl, readBearerToken, requireAuthenticationLevel, requireAuthenticationMethod, requireCallerKind, requireClaim, requireClient, requireGroup, requireOrganization, requirePermission, requireRecentAuthentication, requireRole, requireScope, toForbiddenChallenge, toProblemDetails };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthioResourceAccess, AuthioResourceAccessSource, AuthioError, AuthioConnection, AuthioDiscoveryClient, AuthioClient, AuthioConnectionOptions, AuthioClientOptions,
|
|
1
|
+
import { AuthioCallerKind, AuthioCredentialForm, AuthioResourceAccess, AuthioIntrospectionResult, AuthioResourceAccessSource, AuthioClock, AuthioError, AuthioTokenFailure, AuthioConnection, AuthioDiscoveryClient, AuthioClient, AuthioConnectionOptions, AuthioClientOptions, AuthioEncryptionKeySource, AuthioWebhookEvent, AuthioWebhookDataByType, AuthioTypedWebhookEvent, AuthioClientCredentialsToken } from '@hyper.authio/client';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The party acting for the subject, from the `act` claim (RFC 8693): who exchanged the token, nested when the chain
|
|
@@ -7,8 +7,17 @@ import { AuthioResourceAccess, AuthioResourceAccessSource, AuthioError, AuthioCo
|
|
|
7
7
|
interface AuthioActor {
|
|
8
8
|
readonly clientId: string | undefined;
|
|
9
9
|
readonly subject: string | undefined;
|
|
10
|
+
/** `name`, on an impersonation: the administrator's display name. */
|
|
11
|
+
readonly name: string | undefined;
|
|
10
12
|
readonly actor: AuthioActor | undefined;
|
|
11
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* The administrator who impersonates the subject (an `act` with `sub` and no `client_id`).
|
|
16
|
+
*/
|
|
17
|
+
interface AuthioImpersonator {
|
|
18
|
+
readonly subject: string;
|
|
19
|
+
readonly name: string | undefined;
|
|
20
|
+
}
|
|
12
21
|
/**
|
|
13
22
|
* Where the user reads flat (non-`*_resource_access`) roles and groups from.
|
|
14
23
|
*/
|
|
@@ -31,6 +40,41 @@ interface AuthioUserClaimSettings {
|
|
|
31
40
|
declare class AuthioUser {
|
|
32
41
|
/** `sub`: the person's id, or the credential's for a machine caller. */
|
|
33
42
|
readonly subject: string;
|
|
43
|
+
/**
|
|
44
|
+
* Who called: `user` (a person signed in), `client` (a client as itself), `consumer` (a machine consumer of a
|
|
45
|
+
* client) or `account_credential` (a credential of an Authio account).
|
|
46
|
+
*/
|
|
47
|
+
readonly kind: AuthioCallerKind;
|
|
48
|
+
/**
|
|
49
|
+
* How a machine caller proved who it is (`client_secret`, `personal_access_token`, `api_key`,
|
|
50
|
+
* `consumer_api_key`); `undefined` for a person or a client.
|
|
51
|
+
*/
|
|
52
|
+
readonly credentialForm: AuthioCredentialForm | undefined;
|
|
53
|
+
/** `consumer_name`, for a consumer. */
|
|
54
|
+
readonly consumerName: string | undefined;
|
|
55
|
+
/** `credential_name`, for an account credential. */
|
|
56
|
+
readonly credentialName: string | undefined;
|
|
57
|
+
/** `owner_user_id`: the person who made the credential. */
|
|
58
|
+
readonly ownerUserId: string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* `owner_username`: the person who made the credential. On an account credential Authio wrote it to
|
|
61
|
+
* `consumer_name` before, which is read when `owner_username` is absent.
|
|
62
|
+
*/
|
|
63
|
+
readonly ownerUsername: string | undefined;
|
|
64
|
+
/** `credential_realm`: the one realm an account credential is limited to. */
|
|
65
|
+
readonly credentialRealm: string | undefined;
|
|
66
|
+
/** `credential_client`: the one client an account credential is limited to. */
|
|
67
|
+
readonly credentialClient: string | undefined;
|
|
68
|
+
/** Whether an administrator impersonates the subject. */
|
|
69
|
+
readonly impersonated: boolean;
|
|
70
|
+
/** The administrator impersonating the subject. */
|
|
71
|
+
readonly impersonator: AuthioImpersonator | undefined;
|
|
72
|
+
/** Whether a client acts for the subject through a delegation (`act` with `client_id`). */
|
|
73
|
+
readonly delegated: boolean;
|
|
74
|
+
/** The clients acting for the subject, outermost first. */
|
|
75
|
+
readonly actorChain: readonly string[];
|
|
76
|
+
/** `auth_time`, in seconds since the epoch. */
|
|
77
|
+
readonly authTime: number | undefined;
|
|
34
78
|
/** The client the token was issued to (`azp`, else `client_id`). */
|
|
35
79
|
readonly clientId: string | undefined;
|
|
36
80
|
/** `sid`. */
|
|
@@ -86,10 +130,16 @@ declare class AuthioUser {
|
|
|
86
130
|
* @param claims The token's payload, or the introspection answer's members.
|
|
87
131
|
* @param settings Where flat roles and groups are read from.
|
|
88
132
|
* @param token The access token, kept for forwarding and on-behalf-of.
|
|
133
|
+
* @param source Where the claims come from: a JWT (default) or an introspection answer. An introspection answer for
|
|
134
|
+
* a consumer that reports no `exp` and no `actor_type` is the consumer's API key (Authio reports no lifetime for a
|
|
135
|
+
* key), so its `credentialForm` is `consumer_api_key`.
|
|
136
|
+
*/
|
|
137
|
+
constructor(claims: Readonly<Record<string, unknown>>, settings?: AuthioUserClaimSettings, token?: string, source?: "token" | "introspection");
|
|
138
|
+
/**
|
|
139
|
+
* Reads the caller from an introspection answer: `client_id` becomes `azp`, `username` becomes
|
|
140
|
+
* `preferred_username`, and `token_type` becomes `typ` unless it is `api_key` (a consumer's API key).
|
|
89
141
|
*/
|
|
90
|
-
|
|
91
|
-
/** Whether an actor exchanged the token on the subject's behalf. */
|
|
92
|
-
get isDelegated(): boolean;
|
|
142
|
+
static fromIntrospection(result: AuthioIntrospectionResult, settings?: AuthioUserClaimSettings, token?: string): AuthioUser;
|
|
93
143
|
/** Whether the scope was granted. */
|
|
94
144
|
hasScope(scope: string): boolean;
|
|
95
145
|
/**
|
|
@@ -138,6 +188,10 @@ interface AuthioRuleFailure {
|
|
|
138
188
|
readonly error?: "insufficient_scope" | "insufficient_user_authentication";
|
|
139
189
|
/** The required scopes, for `insufficient_scope`. */
|
|
140
190
|
readonly scope?: string;
|
|
191
|
+
/** The context classes to ask for again, for `insufficient_user_authentication` (RFC 9470 `acr_values`). */
|
|
192
|
+
readonly acrValues?: string;
|
|
193
|
+
/** How old the sign-in may be, in seconds, for `insufficient_user_authentication` (RFC 9470 `max_age`). */
|
|
194
|
+
readonly maxAge?: number;
|
|
141
195
|
}
|
|
142
196
|
/**
|
|
143
197
|
* A condition on the caller.
|
|
@@ -150,7 +204,8 @@ interface AuthioRule {
|
|
|
150
204
|
}
|
|
151
205
|
/**
|
|
152
206
|
* Checks every rule. On refusal the message joins every rule's, and the error is the one asking for a stronger
|
|
153
|
-
* sign-in, else the first one
|
|
207
|
+
* sign-in (with the strongest `acr_values` and the shortest `max_age` the failing rules ask for), else the first one
|
|
208
|
+
* that has an error.
|
|
154
209
|
*/
|
|
155
210
|
declare function authorize(user: AuthioUser, ...rules: AuthioRule[]): AuthioRuleFailure | undefined;
|
|
156
211
|
/**
|
|
@@ -184,13 +239,30 @@ declare function requireClaim(type: string, ...values: string[]): AuthioRule;
|
|
|
184
239
|
*/
|
|
185
240
|
declare function requireOrganization(organization?: string): AuthioRule;
|
|
186
241
|
/**
|
|
187
|
-
* Requires a minimum authentication level (`acr`): 1 one factor, 2 several, 3 one of them phishing-resistant.
|
|
242
|
+
* Requires a minimum authentication level (`acr`): 1 one factor, 2 several, 3 one of them phishing-resistant. The
|
|
243
|
+
* refusal asks for that level again (`acr_values`), and for a sign-in at most `maxAge` seconds old when given.
|
|
244
|
+
*/
|
|
245
|
+
declare function requireAuthenticationLevel(minimumLevel: number, options?: {
|
|
246
|
+
maxAge?: number;
|
|
247
|
+
clock?: AuthioClock;
|
|
248
|
+
}): AuthioRule;
|
|
249
|
+
/**
|
|
250
|
+
* Requires authentication methods (`amr`, case-insensitive), such as `otp`, `swk` or `fed`. The refusal asks for the
|
|
251
|
+
* context class the methods imply (`2` for `mfa`/`otp`/`mca`, `3` for `swk`/`hwk`), or for `acrValues` when given.
|
|
252
|
+
*/
|
|
253
|
+
declare function requireAuthenticationMethod(methods: string | readonly string[], match?: AuthioMatch, options?: {
|
|
254
|
+
acrValues?: string;
|
|
255
|
+
}): AuthioRule;
|
|
256
|
+
/**
|
|
257
|
+
* Requires a sign-in at most `maxAge` seconds old (`auth_time`); the refusal asks for it with `max_age` (RFC 9470).
|
|
188
258
|
*/
|
|
189
|
-
declare function
|
|
259
|
+
declare function requireRecentAuthentication(maxAge: number, options?: {
|
|
260
|
+
clock?: AuthioClock;
|
|
261
|
+
}): AuthioRule;
|
|
190
262
|
/**
|
|
191
|
-
* Requires
|
|
263
|
+
* Requires the caller to be of one of the kinds: `user`, `client`, `consumer`, `account_credential`.
|
|
192
264
|
*/
|
|
193
|
-
declare function
|
|
265
|
+
declare function requireCallerKind(kinds: AuthioCallerKind | readonly AuthioCallerKind[]): AuthioRule;
|
|
194
266
|
/**
|
|
195
267
|
* Requires the token to have been issued to one of the clients (`azp`, else `client_id`).
|
|
196
268
|
*/
|
|
@@ -213,10 +285,18 @@ declare class AuthioBearerError extends AuthioError {
|
|
|
213
285
|
readonly error: "invalid_token" | undefined;
|
|
214
286
|
/** Why the token was refused, safe to send to the caller. */
|
|
215
287
|
readonly description: string | undefined;
|
|
288
|
+
/** Why the token was refused, as a stable code; `undefined` when there was no token or Authio could not be asked. */
|
|
289
|
+
readonly reason: AuthioTokenFailure | "inactive" | "unconfirmed" | undefined;
|
|
290
|
+
/** The API's protected resource metadata URL (RFC 9728), sent as `resource_metadata` when configured. */
|
|
291
|
+
readonly resourceMetadata: string | undefined;
|
|
216
292
|
constructor(description: string | undefined, options?: {
|
|
217
293
|
error?: "invalid_token" | undefined;
|
|
218
294
|
cause?: unknown;
|
|
295
|
+
reason?: AuthioTokenFailure | "inactive" | "unconfirmed";
|
|
296
|
+
resourceMetadata?: string;
|
|
219
297
|
});
|
|
298
|
+
/** The same refusal, pointing at the API's protected resource metadata. */
|
|
299
|
+
withResourceMetadata(resourceMetadata: string | undefined): AuthioBearerError;
|
|
220
300
|
/** The `WWW-Authenticate` value. */
|
|
221
301
|
get wwwAuthenticate(): string;
|
|
222
302
|
}
|
|
@@ -231,8 +311,8 @@ declare class AuthioForbiddenError extends AuthioError {
|
|
|
231
311
|
get wwwAuthenticate(): string | undefined;
|
|
232
312
|
}
|
|
233
313
|
/**
|
|
234
|
-
* The `WWW-Authenticate` value of a refusal: `insufficient_scope` (with `scope`) or
|
|
235
|
-
* `
|
|
314
|
+
* The `WWW-Authenticate` value of a refusal: `insufficient_scope` (with `scope`) or `insufficient_user_authentication`
|
|
315
|
+
* (with `acr_values` and `max_age`, RFC 9470).
|
|
236
316
|
*/
|
|
237
317
|
declare function toForbiddenChallenge(failure: AuthioRuleFailure): string | undefined;
|
|
238
318
|
/**
|
|
@@ -246,15 +326,27 @@ declare function toProblemDetails(error: AuthioBearerError | AuthioForbiddenErro
|
|
|
246
326
|
* - `none`: the JWT is validated locally (signature, issuer, audience, lifetime). Fastest; a revoked token stays
|
|
247
327
|
* valid until it expires.
|
|
248
328
|
* - `activeCheck`: validated locally, then confirmed active by introspection (cached per `jti`).
|
|
249
|
-
* - `introspectionOnly`: introspection alone, for opaque (reference) or encrypted
|
|
329
|
+
* - `introspectionOnly`: introspection alone, for opaque (reference) tokens, or encrypted ones without the key.
|
|
250
330
|
*/
|
|
251
331
|
type AuthioIntrospectionMode = "none" | "activeCheck" | "introspectionOnly";
|
|
252
332
|
/**
|
|
253
333
|
* How an API validates Authio access tokens.
|
|
254
334
|
*/
|
|
255
335
|
interface AuthioVerifierOptions extends AuthioConnectionOptions, AuthioUserClaimSettings {
|
|
256
|
-
/** The audiences this API accepts: its resource identifier (RFC 8707) or client id. Required. */
|
|
257
|
-
audiences
|
|
336
|
+
/** The audiences this API accepts: its resource identifier (RFC 8707) or client id. Required unless `resource` is set. */
|
|
337
|
+
audiences?: string | readonly string[];
|
|
338
|
+
/**
|
|
339
|
+
* The API's own resource identifier (RFC 8707), such as `https://orders.example.com`. Added to `audiences`, and
|
|
340
|
+
* the `resource` of its protected resource metadata (RFC 9728).
|
|
341
|
+
*/
|
|
342
|
+
resource?: string;
|
|
343
|
+
/**
|
|
344
|
+
* Points `401` challenges at the API's protected resource metadata (RFC 9728) with `resource_metadata`: `true`
|
|
345
|
+
* for `{origin of resource}/.well-known/oauth-protected-resource{path of resource}`, or the URL itself. Off by default.
|
|
346
|
+
*/
|
|
347
|
+
resourceMetadata?: boolean | string;
|
|
348
|
+
/** Scopes every request must carry (all of them); `authioBearer` answers `403 insufficient_scope` otherwise. */
|
|
349
|
+
requiredScopes?: readonly string[];
|
|
258
350
|
/** Defaults to `none`. */
|
|
259
351
|
introspection?: AuthioIntrospectionMode;
|
|
260
352
|
/**
|
|
@@ -271,6 +363,15 @@ interface AuthioVerifierOptions extends AuthioConnectionOptions, AuthioUserClaim
|
|
|
271
363
|
validAlgorithms?: readonly string[];
|
|
272
364
|
/** Refuses a token whose `typ` claim is present and not `Bearer` (an ID token, for one). Defaults to `true`. */
|
|
273
365
|
rejectNonAccessTokens?: boolean;
|
|
366
|
+
/**
|
|
367
|
+
* The private half of the encryption key Authio encrypts this API's access tokens to (the resource server's or its
|
|
368
|
+
* client's), so encrypted tokens are decrypted and validated locally (RSA-OAEP, RSA-OAEP-256).
|
|
369
|
+
*/
|
|
370
|
+
clientEncryptionKey?: AuthioEncryptionKeySource;
|
|
371
|
+
/** A PEM or JWK file holding `clientEncryptionKey` (Node only). */
|
|
372
|
+
clientEncryptionKeyPath?: string;
|
|
373
|
+
/** Accepted for parity with the other Authio SDKs; RSA1_5 stays refused, because Node cannot decrypt it. */
|
|
374
|
+
allowLegacyEncryptionAlgorithms?: boolean;
|
|
274
375
|
}
|
|
275
376
|
/**
|
|
276
377
|
* Validates Authio access tokens and reads the caller.
|
|
@@ -282,6 +383,12 @@ interface AuthioVerifier {
|
|
|
282
383
|
readonly discovery: AuthioDiscoveryClient;
|
|
283
384
|
/** The accepted audiences. */
|
|
284
385
|
readonly audiences: readonly string[];
|
|
386
|
+
/** The API's resource identifier, when configured. */
|
|
387
|
+
readonly resource: string | undefined;
|
|
388
|
+
/** The protected resource metadata URL sent in challenges, when turned on. */
|
|
389
|
+
readonly resourceMetadataUrl: string | undefined;
|
|
390
|
+
/** Scopes every request must carry. */
|
|
391
|
+
readonly requiredScopes: readonly string[];
|
|
285
392
|
/** The introspection mode. */
|
|
286
393
|
readonly introspection: AuthioIntrospectionMode;
|
|
287
394
|
/** The client used for introspection, when there is one. */
|
|
@@ -307,7 +414,7 @@ declare const AuthioBearerErrorDescriptions: {
|
|
|
307
414
|
readonly Inactive: "Authio reports the token as not active to this API's client. It was revoked or has expired or its session ended; or this API's client is not the introspection client of the resource server the token is for.";
|
|
308
415
|
readonly Unconfirmed: "Authio could not be reached to confirm that the token is active.";
|
|
309
416
|
readonly Empty: "The token is empty.";
|
|
310
|
-
readonly Encrypted: "The token is encrypted; validate it with introspection ('introspectionOnly').";
|
|
417
|
+
readonly Encrypted: "The token is encrypted; set clientEncryptionKey to decrypt it, or validate it with introspection ('introspectionOnly').";
|
|
311
418
|
readonly SigningKeysUnavailable: "Authio could not be reached to read its signing keys.";
|
|
312
419
|
};
|
|
313
420
|
/**
|
|
@@ -321,6 +428,48 @@ declare function createAuthioVerifier(options: AuthioVerifierOptions): AuthioVer
|
|
|
321
428
|
*/
|
|
322
429
|
declare function readBearerToken(header: string | null | undefined): string | undefined;
|
|
323
430
|
|
|
431
|
+
/**
|
|
432
|
+
* What an API publishes about itself as a protected resource (RFC 9728).
|
|
433
|
+
*/
|
|
434
|
+
interface AuthioProtectedResourceMetadataOptions extends Pick<AuthioConnectionOptions, "issuer" | "authority" | "realm"> {
|
|
435
|
+
/** The API's resource identifier (RFC 8707), such as `https://orders.example.com/api`. Required. */
|
|
436
|
+
resource: string;
|
|
437
|
+
/** Scopes a client can ask for to call the API. */
|
|
438
|
+
scopesSupported?: readonly string[];
|
|
439
|
+
/** A name to show to people. */
|
|
440
|
+
resourceName?: string;
|
|
441
|
+
/** A page documenting the API. */
|
|
442
|
+
resourceDocumentation?: string;
|
|
443
|
+
/** Further members, sent as given. */
|
|
444
|
+
extra?: Record<string, unknown>;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* The protected resource metadata document (RFC 9728 §2).
|
|
448
|
+
*/
|
|
449
|
+
interface AuthioProtectedResourceMetadata {
|
|
450
|
+
resource: string;
|
|
451
|
+
authorization_servers: string[];
|
|
452
|
+
bearer_methods_supported: string[];
|
|
453
|
+
scopes_supported?: string[];
|
|
454
|
+
resource_name?: string;
|
|
455
|
+
resource_documentation?: string;
|
|
456
|
+
[member: string]: unknown;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Where a resource's metadata is published: `{origin}/.well-known/oauth-protected-resource{path}` (RFC 9728 §3.1),
|
|
460
|
+
* the path being the resource's own, without a trailing slash.
|
|
461
|
+
*/
|
|
462
|
+
declare function protectedResourceMetadataUrl(resource: string): string;
|
|
463
|
+
/**
|
|
464
|
+
* The path a resource's metadata is served at on the API itself: `/.well-known/oauth-protected-resource{path}`.
|
|
465
|
+
*/
|
|
466
|
+
declare function protectedResourceMetadataPath(resource: string): string;
|
|
467
|
+
/**
|
|
468
|
+
* Builds the API's protected resource metadata: the resource, the realm's issuer as its authorization server, bearer
|
|
469
|
+
* tokens in the `Authorization` header, and the optional scopes, name and documentation.
|
|
470
|
+
*/
|
|
471
|
+
declare function createProtectedResourceMetadata(options: AuthioProtectedResourceMetadataOptions): AuthioProtectedResourceMetadata;
|
|
472
|
+
|
|
324
473
|
/**
|
|
325
474
|
* Remembers delivered event ids, so a redelivery is acknowledged without running the handlers twice.
|
|
326
475
|
*/
|
|
@@ -436,4 +585,4 @@ declare function createOnBehalfOf(options: {
|
|
|
436
585
|
tokenRefreshSkew?: number;
|
|
437
586
|
}): AuthioOnBehalfOf;
|
|
438
587
|
|
|
439
|
-
export { type AuthioActor, AuthioBearerError, AuthioBearerErrorDescriptions, type AuthioDownstreamSubject, AuthioForbiddenError, type AuthioIntrospectionMode, type AuthioMatch, type AuthioOnBehalfOf, type AuthioRule, type AuthioRuleFailure, AuthioUser, type AuthioUserClaimSettings, type AuthioVerifier, type AuthioVerifierOptions, type AuthioWebhookDeduplicationStore, type AuthioWebhookHandler, type AuthioWebhookOptions, type AuthioWebhookOutcome, type AuthioWebhooks, allOf, anyOf, authorize, createAuthioVerifier, createAuthioWebhooks, createForwardingFetch, createMemoryDeduplicationStore, createOnBehalfOf, readBearerToken, requireAuthenticationLevel, requireAuthenticationMethod, requireClaim, requireClient, requireGroup, requireOrganization, requirePermission, requireRole, requireScope, toForbiddenChallenge, toProblemDetails };
|
|
588
|
+
export { type AuthioActor, AuthioBearerError, AuthioBearerErrorDescriptions, type AuthioDownstreamSubject, AuthioForbiddenError, type AuthioImpersonator, type AuthioIntrospectionMode, type AuthioMatch, type AuthioOnBehalfOf, type AuthioProtectedResourceMetadata, type AuthioProtectedResourceMetadataOptions, type AuthioRule, type AuthioRuleFailure, AuthioUser, type AuthioUserClaimSettings, type AuthioVerifier, type AuthioVerifierOptions, type AuthioWebhookDeduplicationStore, type AuthioWebhookHandler, type AuthioWebhookOptions, type AuthioWebhookOutcome, type AuthioWebhooks, allOf, anyOf, authorize, createAuthioVerifier, createAuthioWebhooks, createForwardingFetch, createMemoryDeduplicationStore, createOnBehalfOf, createProtectedResourceMetadata, protectedResourceMetadataPath, protectedResourceMetadataUrl, readBearerToken, requireAuthenticationLevel, requireAuthenticationMethod, requireCallerKind, requireClaim, requireClient, requireGroup, requireOrganization, requirePermission, requireRecentAuthentication, requireRole, requireScope, toForbiddenChallenge, toProblemDetails };
|