@hyper.authio/server 0.0.0-stage → 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 +144 -2
- package/dist/index.cjs +913 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +588 -0
- package/dist/index.d.ts +588 -0
- package/dist/index.js +883 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
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
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The party acting for the subject, from the `act` claim (RFC 8693): who exchanged the token, nested when the chain
|
|
5
|
+
* is longer.
|
|
6
|
+
*/
|
|
7
|
+
interface AuthioActor {
|
|
8
|
+
readonly clientId: string | undefined;
|
|
9
|
+
readonly subject: string | undefined;
|
|
10
|
+
/** `name`, on an impersonation: the administrator's display name. */
|
|
11
|
+
readonly name: string | undefined;
|
|
12
|
+
readonly actor: AuthioActor | undefined;
|
|
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
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Where the user reads flat (non-`*_resource_access`) roles and groups from.
|
|
23
|
+
*/
|
|
24
|
+
interface AuthioUserClaimSettings {
|
|
25
|
+
/**
|
|
26
|
+
* Claims holding role names directly, such as one written by a claim mapper with the Role source. They count for
|
|
27
|
+
* `hasRole` without a source filter. Defaults to `["role"]`.
|
|
28
|
+
*/
|
|
29
|
+
roleClaims?: readonly string[];
|
|
30
|
+
/**
|
|
31
|
+
* Claims holding group names, such as one written by a claim mapper with the Group source. Defaults to
|
|
32
|
+
* `["groups"]`.
|
|
33
|
+
*/
|
|
34
|
+
groupClaims?: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The caller of an API, read from a validated access token or an introspection answer: identity, every form of
|
|
38
|
+
* permission Authio issues, and the raw claims for anything else.
|
|
39
|
+
*/
|
|
40
|
+
declare class AuthioUser {
|
|
41
|
+
/** `sub`: the person's id, or the credential's for a machine caller. */
|
|
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;
|
|
78
|
+
/** The client the token was issued to (`azp`, else `client_id`). */
|
|
79
|
+
readonly clientId: string | undefined;
|
|
80
|
+
/** `sid`. */
|
|
81
|
+
readonly sessionId: string | undefined;
|
|
82
|
+
/** `jti`. */
|
|
83
|
+
readonly tokenId: string | undefined;
|
|
84
|
+
/** `aud`. */
|
|
85
|
+
readonly audiences: readonly string[];
|
|
86
|
+
/** The granted scopes. */
|
|
87
|
+
readonly scopes: readonly string[];
|
|
88
|
+
/** The roles of the seven `*_resource_access` claims, with their source and permissions. */
|
|
89
|
+
readonly resourceAccess: AuthioResourceAccess;
|
|
90
|
+
/** Every role name: the `*_resource_access` roles, then the flat role claims. */
|
|
91
|
+
readonly roles: readonly string[];
|
|
92
|
+
/** Resource → every method any role allows on it. */
|
|
93
|
+
readonly permissions: Readonly<Record<string, readonly string[]>>;
|
|
94
|
+
/** The group names of the group claims. */
|
|
95
|
+
readonly groups: readonly string[];
|
|
96
|
+
/** `org_id`. */
|
|
97
|
+
readonly organizationId: string | undefined;
|
|
98
|
+
/** `org_alias`. */
|
|
99
|
+
readonly organizationAlias: string | undefined;
|
|
100
|
+
/** `account_id`. */
|
|
101
|
+
readonly accountId: string | undefined;
|
|
102
|
+
/** `acr`. */
|
|
103
|
+
readonly acr: string | undefined;
|
|
104
|
+
/** `acr` as a number: 1 one factor, 2 several, 3 one of them phishing-resistant. */
|
|
105
|
+
readonly authenticationLevel: number | undefined;
|
|
106
|
+
/** `amr`. */
|
|
107
|
+
readonly authenticationMethods: readonly string[];
|
|
108
|
+
/** `idp`. */
|
|
109
|
+
readonly identityProvider: string | undefined;
|
|
110
|
+
/** `auth_time`. */
|
|
111
|
+
readonly authenticatedAt: Date | undefined;
|
|
112
|
+
/** `act`. */
|
|
113
|
+
readonly actor: AuthioActor | undefined;
|
|
114
|
+
/** `delegation_id`. */
|
|
115
|
+
readonly delegationId: string | undefined;
|
|
116
|
+
readonly email: string | undefined;
|
|
117
|
+
readonly emailVerified: boolean | undefined;
|
|
118
|
+
readonly name: string | undefined;
|
|
119
|
+
readonly preferredUsername: string | undefined;
|
|
120
|
+
/** `credential_type`, on a token issued to an account credential or a consumer. */
|
|
121
|
+
readonly credentialType: string | undefined;
|
|
122
|
+
/** `credential_id`. */
|
|
123
|
+
readonly credentialId: string | undefined;
|
|
124
|
+
/** Every claim, as the token or the introspection answer carried it. */
|
|
125
|
+
readonly claims: Readonly<Record<string, unknown>>;
|
|
126
|
+
/** The access token the user was read from. Not enumerable, so it stays out of logs and JSON. */
|
|
127
|
+
readonly token: string | undefined;
|
|
128
|
+
private readonly flatRoles;
|
|
129
|
+
/**
|
|
130
|
+
* @param claims The token's payload, or the introspection answer's members.
|
|
131
|
+
* @param settings Where flat roles and groups are read from.
|
|
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).
|
|
141
|
+
*/
|
|
142
|
+
static fromIntrospection(result: AuthioIntrospectionResult, settings?: AuthioUserClaimSettings, token?: string): AuthioUser;
|
|
143
|
+
/** Whether the scope was granted. */
|
|
144
|
+
hasScope(scope: string): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Whether the user holds the role. Without sources, from any `*_resource_access` claim or a flat role claim; with
|
|
147
|
+
* sources, only from those `*_resource_access` claims.
|
|
148
|
+
*/
|
|
149
|
+
hasRole(role: string, options?: {
|
|
150
|
+
sources?: readonly AuthioResourceAccessSource[];
|
|
151
|
+
}): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Authio's grant rule: whether a role (from any source, or only from the given ones) allows `method` on
|
|
154
|
+
* `resource`. Case-insensitive.
|
|
155
|
+
*/
|
|
156
|
+
hasPermission(resource: string, method: string, options?: {
|
|
157
|
+
sources?: readonly AuthioResourceAccessSource[];
|
|
158
|
+
}): boolean;
|
|
159
|
+
/** Whether the user is in the group (exact match). */
|
|
160
|
+
hasGroup(group: string): boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Whether the claim is present (not `null`), and, given values, whether it holds one of them (exact match; an
|
|
163
|
+
* array claim matches when any item does).
|
|
164
|
+
*/
|
|
165
|
+
hasClaim(type: string, ...values: string[]): boolean;
|
|
166
|
+
/**
|
|
167
|
+
* The claim's values as text: one for a scalar, one per item for an array, JSON text for an object.
|
|
168
|
+
*/
|
|
169
|
+
claimValues(type: string): string[];
|
|
170
|
+
/** Every member but the raw token. */
|
|
171
|
+
toJSON(): Record<string, unknown>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* How several required values combine.
|
|
176
|
+
*/
|
|
177
|
+
type AuthioMatch = "any" | "all";
|
|
178
|
+
/**
|
|
179
|
+
* Why a rule refused the caller.
|
|
180
|
+
*/
|
|
181
|
+
interface AuthioRuleFailure {
|
|
182
|
+
/** What is missing, in words. */
|
|
183
|
+
readonly message: string;
|
|
184
|
+
/**
|
|
185
|
+
* The RFC 6750 / RFC 9470 error to put in `WWW-Authenticate`: `insufficient_scope` for scopes,
|
|
186
|
+
* `insufficient_user_authentication` for `acr`/`amr`, none otherwise.
|
|
187
|
+
*/
|
|
188
|
+
readonly error?: "insufficient_scope" | "insufficient_user_authentication";
|
|
189
|
+
/** The required scopes, for `insufficient_scope`. */
|
|
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;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* A condition on the caller.
|
|
198
|
+
*/
|
|
199
|
+
interface AuthioRule {
|
|
200
|
+
/** What the rule requires, for logs. */
|
|
201
|
+
readonly description: string;
|
|
202
|
+
/** `undefined` when the caller satisfies the rule, else why not. */
|
|
203
|
+
check(user: AuthioUser): AuthioRuleFailure | undefined;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Checks every rule. On refusal the message joins every rule's, and the error is the one asking for a stronger
|
|
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.
|
|
209
|
+
*/
|
|
210
|
+
declare function authorize(user: AuthioUser, ...rules: AuthioRule[]): AuthioRuleFailure | undefined;
|
|
211
|
+
/**
|
|
212
|
+
* Requires granted scopes.
|
|
213
|
+
*/
|
|
214
|
+
declare function requireScope(scopes: string | readonly string[], match?: AuthioMatch): AuthioRule;
|
|
215
|
+
/**
|
|
216
|
+
* Requires roles, from any source or only from the given `*_resource_access` claims.
|
|
217
|
+
*/
|
|
218
|
+
declare function requireRole(roles: string | readonly string[], options?: {
|
|
219
|
+
match?: AuthioMatch;
|
|
220
|
+
sources?: readonly AuthioResourceAccessSource[];
|
|
221
|
+
}): AuthioRule;
|
|
222
|
+
/**
|
|
223
|
+
* Requires a permission (`method` on `resource`), granted by a role from any source or only from the given ones.
|
|
224
|
+
*/
|
|
225
|
+
declare function requirePermission(resource: string, method: string, options?: {
|
|
226
|
+
sources?: readonly AuthioResourceAccessSource[];
|
|
227
|
+
}): AuthioRule;
|
|
228
|
+
/**
|
|
229
|
+
* Requires groups, read from the group claims (a claim mapper with the Group source).
|
|
230
|
+
*/
|
|
231
|
+
declare function requireGroup(groups: string | readonly string[], match?: AuthioMatch): AuthioRule;
|
|
232
|
+
/**
|
|
233
|
+
* Requires a claim: present, or holding one of the given values. Fits claim-mapper claims, the user's own claims and
|
|
234
|
+
* any other claim Authio issues.
|
|
235
|
+
*/
|
|
236
|
+
declare function requireClaim(type: string, ...values: string[]): AuthioRule;
|
|
237
|
+
/**
|
|
238
|
+
* Requires an organization context, or a given organization (alias or id, case-insensitive).
|
|
239
|
+
*/
|
|
240
|
+
declare function requireOrganization(organization?: string): AuthioRule;
|
|
241
|
+
/**
|
|
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).
|
|
258
|
+
*/
|
|
259
|
+
declare function requireRecentAuthentication(maxAge: number, options?: {
|
|
260
|
+
clock?: AuthioClock;
|
|
261
|
+
}): AuthioRule;
|
|
262
|
+
/**
|
|
263
|
+
* Requires the caller to be of one of the kinds: `user`, `client`, `consumer`, `account_credential`.
|
|
264
|
+
*/
|
|
265
|
+
declare function requireCallerKind(kinds: AuthioCallerKind | readonly AuthioCallerKind[]): AuthioRule;
|
|
266
|
+
/**
|
|
267
|
+
* Requires the token to have been issued to one of the clients (`azp`, else `client_id`).
|
|
268
|
+
*/
|
|
269
|
+
declare function requireClient(clientIds: string | readonly string[]): AuthioRule;
|
|
270
|
+
/**
|
|
271
|
+
* Requires every rule.
|
|
272
|
+
*/
|
|
273
|
+
declare function allOf(...rules: AuthioRule[]): AuthioRule;
|
|
274
|
+
/**
|
|
275
|
+
* Requires at least one rule; the refusal is the first rule's.
|
|
276
|
+
*/
|
|
277
|
+
declare function anyOf(...rules: AuthioRule[]): AuthioRule;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* The request carries no valid access token: answer `401` with `wwwAuthenticate`.
|
|
281
|
+
*/
|
|
282
|
+
declare class AuthioBearerError extends AuthioError {
|
|
283
|
+
readonly status = 401;
|
|
284
|
+
/** `invalid_token`, or `undefined` when the request had no token at all (RFC 6750 §3.1). */
|
|
285
|
+
readonly error: "invalid_token" | undefined;
|
|
286
|
+
/** Why the token was refused, safe to send to the caller. */
|
|
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;
|
|
292
|
+
constructor(description: string | undefined, options?: {
|
|
293
|
+
error?: "invalid_token" | undefined;
|
|
294
|
+
cause?: unknown;
|
|
295
|
+
reason?: AuthioTokenFailure | "inactive" | "unconfirmed";
|
|
296
|
+
resourceMetadata?: string;
|
|
297
|
+
});
|
|
298
|
+
/** The same refusal, pointing at the API's protected resource metadata. */
|
|
299
|
+
withResourceMetadata(resourceMetadata: string | undefined): AuthioBearerError;
|
|
300
|
+
/** The `WWW-Authenticate` value. */
|
|
301
|
+
get wwwAuthenticate(): string;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* The caller is known but not allowed: answer `403`, with `wwwAuthenticate` when the refusal has a bearer error.
|
|
305
|
+
*/
|
|
306
|
+
declare class AuthioForbiddenError extends AuthioError {
|
|
307
|
+
readonly status = 403;
|
|
308
|
+
readonly failure: AuthioRuleFailure;
|
|
309
|
+
constructor(failure: AuthioRuleFailure);
|
|
310
|
+
/** The `WWW-Authenticate` value, or `undefined` when the refusal is not about scopes or the sign-in. */
|
|
311
|
+
get wwwAuthenticate(): string | undefined;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
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).
|
|
316
|
+
*/
|
|
317
|
+
declare function toForbiddenChallenge(failure: AuthioRuleFailure): string | undefined;
|
|
318
|
+
/**
|
|
319
|
+
* Problem details (RFC 9457) for a `401` or `403`.
|
|
320
|
+
*/
|
|
321
|
+
declare function toProblemDetails(error: AuthioBearerError | AuthioForbiddenError): Record<string, unknown>;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Whether and how Authio's introspection endpoint takes part in validating a token.
|
|
325
|
+
*
|
|
326
|
+
* - `none`: the JWT is validated locally (signature, issuer, audience, lifetime). Fastest; a revoked token stays
|
|
327
|
+
* valid until it expires.
|
|
328
|
+
* - `activeCheck`: validated locally, then confirmed active by introspection (cached per `jti`).
|
|
329
|
+
* - `introspectionOnly`: introspection alone, for opaque (reference) tokens, or encrypted ones without the key.
|
|
330
|
+
*/
|
|
331
|
+
type AuthioIntrospectionMode = "none" | "activeCheck" | "introspectionOnly";
|
|
332
|
+
/**
|
|
333
|
+
* How an API validates Authio access tokens.
|
|
334
|
+
*/
|
|
335
|
+
interface AuthioVerifierOptions extends AuthioConnectionOptions, AuthioUserClaimSettings {
|
|
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[];
|
|
350
|
+
/** Defaults to `none`. */
|
|
351
|
+
introspection?: AuthioIntrospectionMode;
|
|
352
|
+
/**
|
|
353
|
+
* The API's confidential client, for introspection: a client already created, or its options (issuer settings are
|
|
354
|
+
* taken from these options when absent). It must be the client the resource server names as its introspection
|
|
355
|
+
* client, since Authio answers introspection according to who asks.
|
|
356
|
+
*/
|
|
357
|
+
client?: AuthioClient | Omit<AuthioClientOptions, keyof AuthioConnectionOptions>;
|
|
358
|
+
/** Seconds an active introspection answer is kept (never past the token's expiry). Defaults to 30. */
|
|
359
|
+
introspectionCacheDuration?: number;
|
|
360
|
+
/** Seconds of clock skew tolerated on `exp` and `nbf`. Defaults to 30. */
|
|
361
|
+
clockSkew?: number;
|
|
362
|
+
/** Accepted signing algorithms. Defaults to the asymmetric ones (RS*, PS*, ES*). */
|
|
363
|
+
validAlgorithms?: readonly string[];
|
|
364
|
+
/** Refuses a token whose `typ` claim is present and not `Bearer` (an ID token, for one). Defaults to `true`. */
|
|
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;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Validates Authio access tokens and reads the caller.
|
|
378
|
+
*/
|
|
379
|
+
interface AuthioVerifier {
|
|
380
|
+
/** The connection settings. */
|
|
381
|
+
readonly connection: AuthioConnection;
|
|
382
|
+
/** The discovery document. */
|
|
383
|
+
readonly discovery: AuthioDiscoveryClient;
|
|
384
|
+
/** The accepted audiences. */
|
|
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[];
|
|
392
|
+
/** The introspection mode. */
|
|
393
|
+
readonly introspection: AuthioIntrospectionMode;
|
|
394
|
+
/** The client used for introspection, when there is one. */
|
|
395
|
+
readonly client: AuthioClient | undefined;
|
|
396
|
+
/**
|
|
397
|
+
* Validates a token and reads the caller.
|
|
398
|
+
*
|
|
399
|
+
* @throws AuthioBearerError when the token is not valid for this API.
|
|
400
|
+
*/
|
|
401
|
+
verify(token: string, signal?: AbortSignal): Promise<AuthioUser>;
|
|
402
|
+
/**
|
|
403
|
+
* Validates the token of an `Authorization: Bearer` header.
|
|
404
|
+
*
|
|
405
|
+
* @throws AuthioBearerError without an error code when there is no bearer token, with `invalid_token` when it is
|
|
406
|
+
* not valid.
|
|
407
|
+
*/
|
|
408
|
+
verifyAuthorizationHeader(header: string | null | undefined, signal?: AbortSignal): Promise<AuthioUser>;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Error descriptions of the refusals the SDK makes itself.
|
|
412
|
+
*/
|
|
413
|
+
declare const AuthioBearerErrorDescriptions: {
|
|
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.";
|
|
415
|
+
readonly Unconfirmed: "Authio could not be reached to confirm that the token is active.";
|
|
416
|
+
readonly Empty: "The token is empty.";
|
|
417
|
+
readonly Encrypted: "The token is encrypted; set clientEncryptionKey to decrypt it, or validate it with introspection ('introspectionOnly').";
|
|
418
|
+
readonly SigningKeysUnavailable: "Authio could not be reached to read its signing keys.";
|
|
419
|
+
};
|
|
420
|
+
/**
|
|
421
|
+
* Creates a token verifier.
|
|
422
|
+
*
|
|
423
|
+
* @throws AuthioConfigurationError when no audience is given, or introspection is asked for without a client.
|
|
424
|
+
*/
|
|
425
|
+
declare function createAuthioVerifier(options: AuthioVerifierOptions): AuthioVerifier;
|
|
426
|
+
/**
|
|
427
|
+
* The token of an `Authorization: Bearer` header, or `undefined` when the header is absent or of another scheme.
|
|
428
|
+
*/
|
|
429
|
+
declare function readBearerToken(header: string | null | undefined): string | undefined;
|
|
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
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Remembers delivered event ids, so a redelivery is acknowledged without running the handlers twice.
|
|
475
|
+
*/
|
|
476
|
+
interface AuthioWebhookDeduplicationStore {
|
|
477
|
+
/** Records the id; `false` when it was already recorded within the window. */
|
|
478
|
+
tryBegin(eventId: string, windowMs: number): boolean | Promise<boolean>;
|
|
479
|
+
/** Forgets the id, after a handler failed, so the redelivery runs again. */
|
|
480
|
+
release(eventId: string): void | Promise<void>;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* How webhook deliveries are received.
|
|
484
|
+
*/
|
|
485
|
+
interface AuthioWebhookOptions {
|
|
486
|
+
/** The webhook's secret. */
|
|
487
|
+
secret?: string;
|
|
488
|
+
/** Several secrets, while one is being rotated; a delivery signed with any of them is accepted. */
|
|
489
|
+
secrets?: readonly string[];
|
|
490
|
+
/** Seconds a signature's timestamp may differ from now. Defaults to 300. */
|
|
491
|
+
tolerance?: number;
|
|
492
|
+
/** `memory` (default), `none`, or a store shared between instances. */
|
|
493
|
+
deduplication?: "memory" | "none" | AuthioWebhookDeduplicationStore;
|
|
494
|
+
/** Seconds a delivered id is remembered. Defaults to 86400. */
|
|
495
|
+
deduplicationWindow?: number;
|
|
496
|
+
/** The largest body accepted, in bytes. Defaults to 1 MiB. */
|
|
497
|
+
maxBodySize?: number;
|
|
498
|
+
/** The clock. */
|
|
499
|
+
clock?: AuthioClock;
|
|
500
|
+
/** Called when a delivery is refused or a handler fails. */
|
|
501
|
+
onError?: (error: unknown, context: {
|
|
502
|
+
reason: string;
|
|
503
|
+
eventId?: string;
|
|
504
|
+
eventType?: string;
|
|
505
|
+
}) => void;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* A handler of one event type, or of every type.
|
|
509
|
+
*/
|
|
510
|
+
type AuthioWebhookHandler<E extends AuthioWebhookEvent = AuthioWebhookEvent> = (event: E) => void | Promise<void>;
|
|
511
|
+
/**
|
|
512
|
+
* What to answer a delivery with.
|
|
513
|
+
*/
|
|
514
|
+
interface AuthioWebhookOutcome {
|
|
515
|
+
/** `200` handled, duplicate or ping; `400` unreadable; `401` bad or stale signature; `413` too large; `500` a handler failed. */
|
|
516
|
+
readonly status: 200 | 400 | 401 | 413 | 500;
|
|
517
|
+
/** Why, for logs. */
|
|
518
|
+
readonly reason: "handled" | "duplicate" | "unreadable" | "unsigned" | "too_large" | "handler_failed";
|
|
519
|
+
readonly event?: AuthioWebhookEvent;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Receives Authio webhook deliveries: verifies, deduplicates and dispatches them.
|
|
523
|
+
*/
|
|
524
|
+
interface AuthioWebhooks {
|
|
525
|
+
/** Handles one event type, typed. */
|
|
526
|
+
on<T extends keyof AuthioWebhookDataByType>(type: T, handler: AuthioWebhookHandler<AuthioTypedWebhookEvent<T>>): AuthioWebhooks;
|
|
527
|
+
/** Handles another event type, or `*` for every type. */
|
|
528
|
+
on(type: string, handler: AuthioWebhookHandler): AuthioWebhooks;
|
|
529
|
+
/**
|
|
530
|
+
* Handles a delivery: the body exactly as received and the request headers.
|
|
531
|
+
*/
|
|
532
|
+
handle(delivery: {
|
|
533
|
+
body: string | Uint8Array;
|
|
534
|
+
headers: Headers | Record<string, string | string[] | undefined>;
|
|
535
|
+
}): Promise<AuthioWebhookOutcome>;
|
|
536
|
+
/** The largest body accepted, in bytes. */
|
|
537
|
+
readonly maxBodySize: number;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Creates a webhook receiver. Handlers run in registration order; a `*` handler sees every event.
|
|
541
|
+
*
|
|
542
|
+
* @throws AuthioConfigurationError when no secret is configured.
|
|
543
|
+
*/
|
|
544
|
+
declare function createAuthioWebhooks(options: AuthioWebhookOptions): AuthioWebhooks;
|
|
545
|
+
/**
|
|
546
|
+
* A deduplication store kept in this process's memory.
|
|
547
|
+
*/
|
|
548
|
+
declare function createMemoryDeduplicationStore(clock?: AuthioClock): AuthioWebhookDeduplicationStore;
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Who a downstream call is made for: a caller read by the verifier, or the incoming access token itself.
|
|
552
|
+
*/
|
|
553
|
+
type AuthioDownstreamSubject = AuthioUser | string;
|
|
554
|
+
/**
|
|
555
|
+
* A `fetch` that forwards the caller's own access token, unchanged, to a downstream API that accepts the same
|
|
556
|
+
* audience. Sends no `Authorization` when there is no token.
|
|
557
|
+
*/
|
|
558
|
+
declare function createForwardingFetch(subject: AuthioDownstreamSubject | undefined, inner?: typeof fetch): typeof fetch;
|
|
559
|
+
/**
|
|
560
|
+
* Exchanges the caller's token for one addressed to a downstream API (RFC 8693), and caches it.
|
|
561
|
+
*/
|
|
562
|
+
interface AuthioOnBehalfOf {
|
|
563
|
+
/**
|
|
564
|
+
* A token for the downstream API on the caller's behalf: cached per incoming `jti` (else token hash), resource and
|
|
565
|
+
* sorted scopes, renewed `tokenRefreshSkew` before expiry (at most half its lifetime); concurrent callers share
|
|
566
|
+
* one exchange.
|
|
567
|
+
*
|
|
568
|
+
* @throws AuthioError when there is no incoming token.
|
|
569
|
+
*/
|
|
570
|
+
getToken(subject: AuthioDownstreamSubject | undefined, signal?: AbortSignal): Promise<AuthioClientCredentialsToken>;
|
|
571
|
+
/** Drops a cached token; with `accessToken`, only when the cache still holds that token. */
|
|
572
|
+
invalidate(subject: AuthioDownstreamSubject, accessToken?: string): Promise<void>;
|
|
573
|
+
/** A `fetch` that sends the exchanged token, and on a `401` drops it and retries once. */
|
|
574
|
+
fetch(subject: AuthioDownstreamSubject | undefined, inner?: typeof fetch): typeof fetch;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Creates an on-behalf-of exchanger.
|
|
578
|
+
*
|
|
579
|
+
* @param options `client` (the API's confidential client), the downstream `resource` and `scopes`.
|
|
580
|
+
*/
|
|
581
|
+
declare function createOnBehalfOf(options: {
|
|
582
|
+
client: AuthioClient;
|
|
583
|
+
resource?: string;
|
|
584
|
+
scopes?: Iterable<string> | string;
|
|
585
|
+
tokenRefreshSkew?: number;
|
|
586
|
+
}): AuthioOnBehalfOf;
|
|
587
|
+
|
|
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 };
|