@web-ts-toolkit/express-oidc-vault 0.42.2 → 0.47.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.
- package/README.md +261 -51
- package/index.d.mts +300 -9
- package/index.d.ts +300 -9
- package/index.js +619 -194
- package/index.mjs +620 -195
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -10,6 +10,17 @@ interface OidcVaultUserProfile {
|
|
|
10
10
|
preferredUsername?: string;
|
|
11
11
|
[key: string]: unknown;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Stored session identity. Exchange, refresh, and live-session logout compare
|
|
15
|
+
* each defined field verbatim against resolved middleware config before use.
|
|
16
|
+
* Known mismatches fail with 401 `OIDC_VAULT_INVALID_SESSION` without changing
|
|
17
|
+
* the session or cookie. Issuer trailing-slash variants are distinct.
|
|
18
|
+
*
|
|
19
|
+
* Omitted fields remain legacy-compatible and are not backfilled by refresh.
|
|
20
|
+
* Complete isolation requires separate session/alias, exchange-code, and
|
|
21
|
+
* transaction namespaces: exchange spends its code before this check, and
|
|
22
|
+
* logout's stale-alias path has no live identity to check.
|
|
23
|
+
*/
|
|
13
24
|
interface OidcVaultProviderMetadata {
|
|
14
25
|
issuer?: string;
|
|
15
26
|
clientId?: string;
|
|
@@ -35,11 +46,21 @@ interface OidcVaultSession {
|
|
|
35
46
|
* This controls the lifetime of the refresh-token-backed server-side session.
|
|
36
47
|
* It is not derived from upstream OAuth `expires_in`, which only describes the
|
|
37
48
|
* upstream access token lifetime. Leave unset when your application or store
|
|
38
|
-
* owns session lifetime through another policy.
|
|
49
|
+
* owns session lifetime through another policy. `sessionTtlMs` assigns an
|
|
50
|
+
* absolute maximum at callback creation; a precreate hook may shorten it.
|
|
51
|
+
* Refresh preserves this timestamp rather than renewing the lifetime.
|
|
39
52
|
*/
|
|
40
53
|
expiresAt?: number;
|
|
41
54
|
createdAt: number;
|
|
42
55
|
updatedAt: number;
|
|
56
|
+
/**
|
|
57
|
+
* Verified session profile. On refresh with a new `id_token`, the profile
|
|
58
|
+
* is rebuilt from fresh verified ID claims overlaid with freshly fetched
|
|
59
|
+
* matching UserInfo; retained values are never carried forward, so removed
|
|
60
|
+
* provider claims disappear. Application custom attributes belong in
|
|
61
|
+
* `metadata`, not in `user`. Without a new `id_token`, the retained
|
|
62
|
+
* profile is kept verbatim (fresh UserInfo still overlays per key).
|
|
63
|
+
*/
|
|
43
64
|
user?: OidcVaultUserProfile;
|
|
44
65
|
/**
|
|
45
66
|
* Store-portable application metadata.
|
|
@@ -101,6 +122,21 @@ interface ConsumeBackchannelLogoutTokenJtiInput {
|
|
|
101
122
|
declare class OidcVaultStoreConflictError extends Error {
|
|
102
123
|
constructor(message?: string);
|
|
103
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Portable store boundary for JSON-compatible plain objects/arrays and scalar
|
|
127
|
+
* values (strings, finite numbers, booleans, null). Built-in providers capture
|
|
128
|
+
* inputs at invocation before asynchronous work; returned portable data is
|
|
129
|
+
* detached from caller input and stored state. Native BSON/JSON/structured-clone
|
|
130
|
+
* values outside that subset retain provider-specific serialization semantics;
|
|
131
|
+
* opaque native objects have no cross-provider mutation-isolation guarantee.
|
|
132
|
+
*
|
|
133
|
+
* Bulk deletion counts primary records removed, never alias cleanup. Memory
|
|
134
|
+
* excludes expired sessions; MongoDB can count expired rows awaiting TTL cleanup;
|
|
135
|
+
* Redis counts actual primary deletions during a cursor traversal. Counts are not
|
|
136
|
+
* proof that no matches remain: concurrent arrivals can survive. MongoDB scoped
|
|
137
|
+
* deletion repeats until an empty query; Redis traverses once. Neither provides
|
|
138
|
+
* a global logout snapshot, and errors can follow earlier committed deletions.
|
|
139
|
+
*/
|
|
104
140
|
interface OidcVaultStoreProvider {
|
|
105
141
|
/** Upsert an authorization transaction by `state`. */
|
|
106
142
|
createAuthorizationTransaction(input: AuthorizationTransactionInput): Promise<void>;
|
|
@@ -108,29 +144,80 @@ interface OidcVaultStoreProvider {
|
|
|
108
144
|
/** Upsert an exchange code record by `code`. */
|
|
109
145
|
createExchangeCode(input: ExchangeCodeRecordInput): Promise<void>;
|
|
110
146
|
consumeExchangeCode(code: string): Promise<ExchangeCodeRecord | null>;
|
|
111
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* Create a session by `sessionId`, defaulting timestamps and logical lineage when omitted.
|
|
149
|
+
*
|
|
150
|
+
* Duplicate-ID behavior is provider-specific (SVH-06): the memory and
|
|
151
|
+
* MongoDB providers replace the existing session (upsert), while the Redis
|
|
152
|
+
* provider rejects a live duplicate with `OidcVaultStoreConflictError`
|
|
153
|
+
* without changing the existing record or indexes (create-only, preserving
|
|
154
|
+
* RVR-02 index ownership). A rejected create preserves the original record
|
|
155
|
+
* and its subject/logical/provider-session index memberships; an accepted
|
|
156
|
+
* replacement takes over the ID with its own subject/logical/provider-session
|
|
157
|
+
* scope. Reusing an ID that holds only a stale rotation alias clears that
|
|
158
|
+
* alias on memory/Redis, while MongoDB can retain the stale alias row until
|
|
159
|
+
* expiry or lineage cleanup (FU-SVH-05b).
|
|
160
|
+
*
|
|
161
|
+
* Portable callers must always create sessions with a fresh unused
|
|
162
|
+
* `sessionId` and handle `OidcVaultStoreConflictError`: reusing a live ID is
|
|
163
|
+
* non-portable (it may replace or reject), and concurrent reuse races
|
|
164
|
+
* rotation source checks (SVH-08). The core middleware only creates fresh
|
|
165
|
+
* random IDs, so it never depends on duplicate-create behavior.
|
|
166
|
+
*/
|
|
112
167
|
createSession(input: OidcVaultSessionInput): Promise<OidcVaultSession>;
|
|
113
168
|
getSession(sessionId: string): Promise<OidcVaultSession | null>;
|
|
114
169
|
/**
|
|
115
170
|
* Atomically replace an existing session with a distinct unused `nextSession.sessionId`.
|
|
116
171
|
*
|
|
117
172
|
* Providers preserve the existing logical session ID when the next session omits
|
|
118
|
-
* one
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* target
|
|
173
|
+
* one and retain the old public session ID as an in-flight-request revocation
|
|
174
|
+
* alias. Rotation itself does not revoke the lineage. Providers throw
|
|
175
|
+
* `OidcVaultStoreConflictError` without changing source or target data when
|
|
176
|
+
* the source is missing, the target already exists, or the target ID equals
|
|
177
|
+
* the source ID.
|
|
178
|
+
*
|
|
179
|
+
* Each alias expires with its immediate successor session's `expiresAt` and is
|
|
180
|
+
* not extended by later rotations, so an earlier alias can stop working while
|
|
181
|
+
* the lineage is still live. A rotation that assigns an explicitly different
|
|
182
|
+
* logical session ID assigns the new source-ID alias to the new lineage;
|
|
183
|
+
* earlier aliases keep the old lineage and deadline if retained. Memory
|
|
184
|
+
* eagerly retires inactive old-lineage aliases on ownership transitions;
|
|
185
|
+
* MongoDB/Redis can retain them until expiry or explicit cleanup. Use distinct
|
|
186
|
+
* logical IDs for unrelated login families. Sessions without `expiresAt` have
|
|
187
|
+
* provider-specific retention: memory and Redis impose no alias time limit, while
|
|
188
|
+
* MongoDB applies its finite `rotatedSessionAliasRetentionMs` fallback
|
|
189
|
+
* (default 5 minutes). Generic callers must treat an expired alias as a hint,
|
|
190
|
+
* not a revocation channel; core refresh rotates the live session directly and
|
|
191
|
+
* preserves `expiresAt`, so it does not depend on alias lifetime (SVH-05).
|
|
122
192
|
*/
|
|
123
193
|
rotateSession(input: RotateSessionInput): Promise<OidcVaultSession>;
|
|
194
|
+
/**
|
|
195
|
+
* Delete a live public-ID record, or revoke the logical lineage through an
|
|
196
|
+
* unexpired alias when no live record exists. Aliases are not readable through
|
|
197
|
+
* `getSession` and have no issuer/client filter. Scoped/direct deletion preserves
|
|
198
|
+
* unexpired aliases while another live member survives, even in another scope.
|
|
199
|
+
*/
|
|
124
200
|
deleteSession(sessionId: string): Promise<void>;
|
|
201
|
+
/** Revoke a logical lineage without an issuer/client filter; see provider count/concurrency notes. */
|
|
125
202
|
deleteSessionsByLogicalSessionId(input: string | DeleteSessionsByLogicalSessionIdInput): Promise<number>;
|
|
126
203
|
/**
|
|
127
204
|
* Record a backchannel logout JTI once until its finite future expiry.
|
|
128
205
|
*
|
|
129
206
|
* Returns `false` for duplicate, expired, exact-boundary, `NaN`, or infinite
|
|
130
207
|
* expiries. A JTI rejected for invalid or already-expired expiry is not stored.
|
|
208
|
+
*
|
|
209
|
+
* The core middleware (BOV-01) passes an opaque replay key that already
|
|
210
|
+
* namespaces the raw logout-token `jti` by issuer and client ID, so
|
|
211
|
+
* providers must treat `jti` as an opaque string and need no schema change. Pre-BOV-01 raw-`jti` records use
|
|
212
|
+
* a different key shape and expire naturally with the logout-token `exp`;
|
|
213
|
+
* they are never matched by namespaced keys. Retry safety comes from the
|
|
214
|
+
* atomic single-key reservation plus idempotent catch-up deletion in the
|
|
215
|
+
* route handler, not from a multi-key store transaction.
|
|
131
216
|
*/
|
|
132
217
|
consumeBackchannelLogoutTokenJti(input: ConsumeBackchannelLogoutTokenJtiInput): Promise<boolean>;
|
|
218
|
+
/** Delete matching subject sessions, filtering by each supplied issuer/client; string input is unscoped. */
|
|
133
219
|
deleteSessionsBySubject(input: string | DeleteSessionsBySubjectInput): Promise<number>;
|
|
220
|
+
/** Delete matching provider-session IDs, filtering by each supplied issuer/client; string input is unscoped. */
|
|
134
221
|
deleteSessionsByProviderSessionId(input: string | DeleteSessionsByProviderSessionIdInput): Promise<number>;
|
|
135
222
|
}
|
|
136
223
|
interface OidcVaultHookContext {
|
|
@@ -141,6 +228,11 @@ interface OidcVaultHookContext {
|
|
|
141
228
|
metadata?: Record<string, unknown>;
|
|
142
229
|
}
|
|
143
230
|
interface OidcVaultErrorContext extends OidcVaultHookContext {
|
|
231
|
+
/**
|
|
232
|
+
* Original private diagnostic, separate from sanitized browser JSON. Narrow
|
|
233
|
+
* before use; provider transport errors retain the original failure in
|
|
234
|
+
* `error.cause`, while issuer-result validation supplies a TypeError directly.
|
|
235
|
+
*/
|
|
144
236
|
error: unknown;
|
|
145
237
|
}
|
|
146
238
|
interface OidcVaultHooks {
|
|
@@ -148,6 +240,13 @@ interface OidcVaultHooks {
|
|
|
148
240
|
onAuthorizationUrl?(context: OidcVaultHookContext): void | Promise<void>;
|
|
149
241
|
onCallbackTokens?(context: OidcVaultHookContext): void | Promise<void>;
|
|
150
242
|
onUserInfo?(context: OidcVaultHookContext): void | Promise<void>;
|
|
243
|
+
/**
|
|
244
|
+
* May mutate the session before persistence or veto creation by throwing.
|
|
245
|
+
* With `sessionTtlMs`, the session already carries the absolute expiry.
|
|
246
|
+
* After this hook, a valid earlier epoch-millisecond expiry is preserved;
|
|
247
|
+
* removal, extension, or an invalid timestamp restores the configured cap.
|
|
248
|
+
* Without `sessionTtlMs`, application/store lifetime policy is unchanged.
|
|
249
|
+
*/
|
|
151
250
|
onBeforeSessionCreate?(context: OidcVaultHookContext): void | Promise<void>;
|
|
152
251
|
onSessionCreated?(context: OidcVaultHookContext): void | Promise<void>;
|
|
153
252
|
onSessionRefreshed?(context: OidcVaultHookContext): void | Promise<void>;
|
|
@@ -160,12 +259,32 @@ interface IssueTokenInput {
|
|
|
160
259
|
req: Request;
|
|
161
260
|
res: Response;
|
|
162
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Local application credentials returned by `OidcVaultTokenIssuer.issue`.
|
|
264
|
+
* Runtime validation copies only these fields into a fresh result; additional
|
|
265
|
+
* properties are ignored and cannot override the response's session ID/user.
|
|
266
|
+
*/
|
|
163
267
|
interface OidcVaultTokenIssueResult {
|
|
268
|
+
/** Nonempty opaque token string, returned verbatim without trimming. */
|
|
164
269
|
accessToken: string;
|
|
270
|
+
/** Token lifetime in seconds: a finite, nonnegative safe integer (zero is valid). */
|
|
165
271
|
expiresIn: number;
|
|
272
|
+
/** Optional exact literal `Bearer`; omitted/undefined stays absent in JSON. */
|
|
166
273
|
tokenType?: 'Bearer';
|
|
167
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Trusted application token issuer for exchange and refresh. Return a non-null,
|
|
277
|
+
* non-array object satisfying `OidcVaultTokenIssueResult`; only its declared
|
|
278
|
+
* credential fields enter the response. This contains accidental extensions,
|
|
279
|
+
* not arbitrary behavior of trusted issuers/hooks with session/request/response access.
|
|
280
|
+
*/
|
|
168
281
|
interface OidcVaultTokenIssuer {
|
|
282
|
+
/**
|
|
283
|
+
* Invalid results fail inside issuance rollback: revoke the session lineage
|
|
284
|
+
* (including the rotated refresh session), clear a cookie-transport session
|
|
285
|
+
* cookie, and return sanitized HTTP 500 / `OIDC_VAULT_INTERNAL_ERROR`.
|
|
286
|
+
* Field diagnostics are available privately through `hooks.onError`.
|
|
287
|
+
*/
|
|
169
288
|
issue(input: IssueTokenInput): Promise<OidcVaultTokenIssueResult>;
|
|
170
289
|
}
|
|
171
290
|
interface OidcVaultAccessTokenValidationResult {
|
|
@@ -180,13 +299,38 @@ interface OidcVaultAuthContext extends OidcVaultAccessTokenValidationResult {
|
|
|
180
299
|
interface OidcVaultAccessTokenValidator {
|
|
181
300
|
validate(token: string): Promise<OidcVaultAccessTokenValidationResult>;
|
|
182
301
|
}
|
|
302
|
+
interface OidcVaultAccessTokenMiddlewareErrorContext {
|
|
303
|
+
error: unknown;
|
|
304
|
+
req: Request;
|
|
305
|
+
res: Response;
|
|
306
|
+
token?: string;
|
|
307
|
+
auth?: OidcVaultAuthContext;
|
|
308
|
+
}
|
|
183
309
|
interface OidcVaultAccessTokenMiddlewareOptions {
|
|
184
310
|
validator: OidcVaultAccessTokenValidator;
|
|
311
|
+
/**
|
|
312
|
+
* Pre-`next()` veto hook, not a post-commit notification: when it throws,
|
|
313
|
+
* downstream middleware never runs and `req.auth` is detached before the
|
|
314
|
+
* error response is sent. A valid bearer credential plus a failing hook
|
|
315
|
+
* never surfaces as an invalid-token 401: an `OidcVaultHttpError` from the
|
|
316
|
+
* hook keeps its own status/code/client message (a 401 keeps the `Bearer`
|
|
317
|
+
* challenge, other statuses carry no challenge), while any other hook
|
|
318
|
+
* error becomes a sanitized `500 OIDC_VAULT_AUTH_CONTEXT_FAILED` without
|
|
319
|
+
* leaking the original message. The original error is observable via
|
|
320
|
+
* `onError` for private server-side logs.
|
|
321
|
+
*/
|
|
185
322
|
onAuthContext?(input: {
|
|
186
323
|
req: Request;
|
|
187
324
|
res: Response;
|
|
188
325
|
auth: OidcVaultAuthContext;
|
|
189
326
|
}): void | Promise<void>;
|
|
327
|
+
/**
|
|
328
|
+
* Observes the original error for every bearer-middleware failure
|
|
329
|
+
* (extraction, validator, and `onAuthContext` failures) without affecting
|
|
330
|
+
* the sanitized client response. Failures thrown by this observer are
|
|
331
|
+
* swallowed so the original error response is preserved.
|
|
332
|
+
*/
|
|
333
|
+
onError?(context: OidcVaultAccessTokenMiddlewareErrorContext): void | Promise<void>;
|
|
190
334
|
}
|
|
191
335
|
interface OidcVaultAuthenticatedRequest extends Request {
|
|
192
336
|
auth?: OidcVaultAuthContext;
|
|
@@ -204,6 +348,19 @@ declare module 'express-serve-static-core' {
|
|
|
204
348
|
}
|
|
205
349
|
}
|
|
206
350
|
interface OidcVaultConfig {
|
|
351
|
+
/**
|
|
352
|
+
* OIDC issuer identifier, preserved exactly after surrounding-whitespace
|
|
353
|
+
* trimming (no trailing slash is added, so `/tenant`, `/tenant/`, and
|
|
354
|
+
* `/tenant//` remain distinct). Must be an absolute http(s) URL without
|
|
355
|
+
* userinfo, query, or fragment; `http` is accepted for local-test
|
|
356
|
+
* providers. Required alongside `clientId` in discovery and manual modes.
|
|
357
|
+
* Any nonempty endpoint, including `userInfoEndpoint`/`endSessionEndpoint`,
|
|
358
|
+
* selects manual mode: supply `authorizationEndpoint`, `tokenEndpoint`, and
|
|
359
|
+
* `jwksUri`; no discovery or partial overrides. Blank strings are absent
|
|
360
|
+
* after trimming. Discovery responses
|
|
361
|
+
* must carry an exactly equal issuer, and ID/logout tokens are validated
|
|
362
|
+
* against this exact identifier.
|
|
363
|
+
*/
|
|
207
364
|
issuer?: string;
|
|
208
365
|
authorizationEndpoint?: string;
|
|
209
366
|
tokenEndpoint?: string;
|
|
@@ -215,6 +372,19 @@ interface OidcVaultConfig {
|
|
|
215
372
|
scopes?: string;
|
|
216
373
|
}
|
|
217
374
|
interface OidcVaultLogoutResult {
|
|
375
|
+
/**
|
|
376
|
+
* Successful live-session logout commits revocation before upstream work
|
|
377
|
+
* (and clears the session cookie under cookie transport). Known foreign
|
|
378
|
+
* live sessions instead fail with 401. Without a live session, success means
|
|
379
|
+
* stale-alias deletion was attempted; an expired alias may no longer revoke
|
|
380
|
+
* a live lineage. Stateless application access tokens are not invalidated.
|
|
381
|
+
* Local-only logout (`redirect` unset or `false`) never contacts the provider.
|
|
382
|
+
* Redirected logout (`redirect: true`)
|
|
383
|
+
* treats the upstream end-session redirect as best-effort: when provider
|
|
384
|
+
* discovery fails or no `endSessionEndpoint` is available, the route still
|
|
385
|
+
* returns this local success. Discovery errors reach `onError` without
|
|
386
|
+
* undoing revocation or skipping the live session's `onLogout` notification.
|
|
387
|
+
*/
|
|
218
388
|
loggedOut: true;
|
|
219
389
|
}
|
|
220
390
|
interface OidcVaultBackchannelLogoutResult {
|
|
@@ -222,19 +392,51 @@ interface OidcVaultBackchannelLogoutResult {
|
|
|
222
392
|
revokedSessions: number;
|
|
223
393
|
}
|
|
224
394
|
interface OidcVaultExchangeResult extends Partial<OidcVaultTokenIssueResult> {
|
|
395
|
+
/** Authoritative vault handle in body transport; omitted from cookie-transport JSON. */
|
|
225
396
|
sessionId?: string;
|
|
397
|
+
/** Session profile; extra token-issuer result properties cannot override it. */
|
|
226
398
|
user?: OidcVaultUserProfile;
|
|
227
399
|
}
|
|
228
400
|
type OidcVaultSessionTransport = 'body' | 'cookie';
|
|
229
401
|
type OidcVaultCookieDeploymentMode = 'same-origin' | 'same-site' | 'cross-site';
|
|
230
402
|
type OidcVaultCookieSameSite = 'lax' | 'strict' | 'none';
|
|
231
403
|
interface OidcVaultCookieOptions {
|
|
404
|
+
/**
|
|
405
|
+
* Session cookie name. Must be a valid HTTP cookie name (printable ASCII
|
|
406
|
+
* token). Names with the `__Secure-` prefix require an effectively Secure
|
|
407
|
+
* cookie; names with the `__Host-` prefix additionally require no
|
|
408
|
+
* `cookie.domain` and `cookie.path: '/'`. Checked against effective
|
|
409
|
+
* serialized values, so `sameSite: 'none'` counts as Secure.
|
|
410
|
+
*/
|
|
232
411
|
name?: string;
|
|
233
412
|
deploymentMode?: OidcVaultCookieDeploymentMode;
|
|
234
413
|
sameSite?: OidcVaultCookieSameSite;
|
|
414
|
+
/**
|
|
415
|
+
* Explicit `Secure` override. When omitted, defaults to `true` for HTTPS
|
|
416
|
+
* `backendOrigin`, `sameSite: 'none'`, or `deploymentMode: 'cross-site'`;
|
|
417
|
+
* otherwise `false` as an intentional HTTP local-development policy
|
|
418
|
+
* (plaintext backends must opt into `secure: true` when served over HTTPS
|
|
419
|
+
* behind a proxy that reports an `http` origin). `SameSite=None` is always
|
|
420
|
+
* serialized with `Secure` regardless of this flag because browsers reject
|
|
421
|
+
* `SameSite=None` without it.
|
|
422
|
+
*/
|
|
235
423
|
secure?: boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Optional cookie `Domain`. Must be a valid cookie domain when set. Must be
|
|
426
|
+
* omitted for `__Host-` prefixed names (host-only requirement).
|
|
427
|
+
*/
|
|
236
428
|
domain?: string;
|
|
429
|
+
/**
|
|
430
|
+
* Cookie `Path`. Must start with `/` and contain only header-safe printable
|
|
431
|
+
* ASCII (no CTLs, DEL, non-ASCII/Unicode, or `;`). `__Host-` prefixed names
|
|
432
|
+
* require exactly `'/'`.
|
|
433
|
+
*/
|
|
237
434
|
path?: string;
|
|
435
|
+
/**
|
|
436
|
+
* Must be `true` or omitted. Middleware creation rejects
|
|
437
|
+
* `httpOnly: false` for cookie session transport; there is no unsafe
|
|
438
|
+
* compatibility switch.
|
|
439
|
+
*/
|
|
238
440
|
httpOnly?: boolean;
|
|
239
441
|
}
|
|
240
442
|
interface OidcVaultOptions {
|
|
@@ -242,18 +444,84 @@ interface OidcVaultOptions {
|
|
|
242
444
|
backendOrigin: string;
|
|
243
445
|
storeProvider: OidcVaultStoreProvider;
|
|
244
446
|
config?: OidcVaultConfig;
|
|
447
|
+
/**
|
|
448
|
+
* Lifecycle hooks shared by reference (not cloned): pre-commit hooks run
|
|
449
|
+
* before durable state changes and can veto by throwing, while
|
|
450
|
+
* `onSessionCreated`/`onSessionRefreshed`/`onLogout` are post-commit
|
|
451
|
+
* notifications whose failures reach `onError` without undoing state.
|
|
452
|
+
* Replacing the caller options object after middleware creation has no
|
|
453
|
+
* effect; the `hooks` service object itself is retained live.
|
|
454
|
+
*/
|
|
245
455
|
hooks?: OidcVaultHooks;
|
|
456
|
+
/** Optional local issuer; when omitted, exchange/refresh return no local token fields. */
|
|
246
457
|
tokenIssuer?: OidcVaultTokenIssuer;
|
|
458
|
+
/**
|
|
459
|
+
* Default browser return target after backend callback completion. Required
|
|
460
|
+
* if login accepts a custom `returnTo`. Remains optional at middleware
|
|
461
|
+
* creation because non-callback routes do not need it; the callback route
|
|
462
|
+
* instead validates its destination (transaction `returnTo` or this value)
|
|
463
|
+
* before any provider call or durable session/code creation and fails with
|
|
464
|
+
* `500 OIDC_VAULT_MISSING_FRONTEND_REDIRECT_URI` when neither is configured.
|
|
465
|
+
*/
|
|
247
466
|
frontendRedirectUri?: string;
|
|
467
|
+
/**
|
|
468
|
+
* Optional provider-registered HTTP(S) URL used in the upstream end-session
|
|
469
|
+
* redirect. Only consulted for redirected logout (`redirect: true`); local
|
|
470
|
+
* logout never contacts the provider, and redirected logout treats upstream
|
|
471
|
+
* discovery failures or an absent endpoint as best-effort (local
|
|
472
|
+
* `200 { loggedOut: true }`, with `onLogout` still delivered for a live
|
|
473
|
+
* session). Discovery errors also reach `onError`.
|
|
474
|
+
*/
|
|
248
475
|
postLogoutRedirectUri?: string;
|
|
249
476
|
fetchUserInfo?: boolean;
|
|
477
|
+
/**
|
|
478
|
+
* Authorization transaction lifetime in milliseconds (default: 10 minutes).
|
|
479
|
+
* Must be a positive safe integer; construction and creation require
|
|
480
|
+
* `now() + TTL` to be an integer within JavaScript Date's epoch range.
|
|
481
|
+
*/
|
|
250
482
|
authorizationTransactionTtlMs?: number;
|
|
483
|
+
/**
|
|
484
|
+
* One-time exchange code lifetime in milliseconds (default: 30 seconds).
|
|
485
|
+
* Same positive-safe-integer and computed-epoch checks as
|
|
486
|
+
* `authorizationTransactionTtlMs`.
|
|
487
|
+
*/
|
|
251
488
|
exchangeCodeTtlMs?: number;
|
|
489
|
+
/**
|
|
490
|
+
* Opt-in absolute server-side session lifetime in milliseconds, measured
|
|
491
|
+
* from callback session creation, not login start. Must be a positive safe
|
|
492
|
+
* integer producing an integer epoch within JavaScript Date's range;
|
|
493
|
+
* checked at construction and again at creation using `now` (or Date.now).
|
|
494
|
+
*
|
|
495
|
+
* Sets `expiresAt` before `onBeforeSessionCreate` and caps it after the hook:
|
|
496
|
+
* hooks may shorten the expiry but cannot extend/remove the maximum (invalid
|
|
497
|
+
* timestamps also restore the cap). Refresh preserves the stored expiry.
|
|
498
|
+
* Independent of upstream OAuth `expires_in`. Unset retains application/
|
|
499
|
+
* store-owned lifetime behavior; no default session expiry is assigned.
|
|
500
|
+
*/
|
|
501
|
+
sessionTtlMs?: number;
|
|
252
502
|
sessionTransport?: OidcVaultSessionTransport;
|
|
253
503
|
cookie?: OidcVaultCookieOptions;
|
|
254
504
|
trustedOrigins?: string[];
|
|
255
505
|
requestBodyLimit?: string | number;
|
|
506
|
+
/**
|
|
507
|
+
* Overall deadline in milliseconds for a single upstream provider HTTP
|
|
508
|
+
* exchange, covering DNS/connect/TLS, response headers, and complete
|
|
509
|
+
* success/error body consumption. Cancellation is attempted promptly but
|
|
510
|
+
* never awaited: completion does not guarantee cleanup of custom streams.
|
|
511
|
+
* Defaults to 5000; must be a positive finite integer.
|
|
512
|
+
*
|
|
513
|
+
* Successful discovery metadata is shared across timeout policies, while
|
|
514
|
+
* in-flight fetches are isolated by `(issuer, providerRequestTimeoutMs)`.
|
|
515
|
+
* Remote JWKS resolvers are isolated by
|
|
516
|
+
* `(jwks_uri, providerRequestTimeoutMs)` because JOSE fixes the fetch
|
|
517
|
+
* timeout at resolver creation; the package JWKS transport additionally
|
|
518
|
+
* bounds JWKS bodies (1 MiB, 100 keys) that JOSE leaves unbounded.
|
|
519
|
+
* Network/reset failures are sanitized endpoint-specific 502s; original
|
|
520
|
+
* transport diagnostics are available privately via `hooks.onError`'s
|
|
521
|
+
* `error.cause`. JOSE timeouts retain `ERR_JWKS_TIMEOUT`.
|
|
522
|
+
*/
|
|
256
523
|
providerRequestTimeoutMs?: number;
|
|
524
|
+
/** Epoch-millisecond clock, also sampled during construction to validate TTLs. Defaults to Date.now. */
|
|
257
525
|
now?: () => number;
|
|
258
526
|
}
|
|
259
527
|
|
|
@@ -275,8 +543,20 @@ interface OidcVaultEnv {
|
|
|
275
543
|
OIDC_SCOPES?: string;
|
|
276
544
|
}
|
|
277
545
|
/**
|
|
278
|
-
* Resolve OIDC configuration from application input.
|
|
279
|
-
*
|
|
546
|
+
* Resolve OIDC configuration from application input.
|
|
547
|
+
*
|
|
548
|
+
* Issuer discovery mode is selected only when an issuer is configured without
|
|
549
|
+
* any nonempty manual endpoint fields. Any such field, including optional
|
|
550
|
+
* `userInfoEndpoint` or `endSessionEndpoint`, selects manual mode: discovery
|
|
551
|
+
* is not used, and `issuer`, `authorizationEndpoint`, `tokenEndpoint`, and
|
|
552
|
+
* `jwksUri` are all required. Blank strings are treated as absent after trimming.
|
|
553
|
+
* `issuer` keeps ID tokens and logout tokens issuer-bound.
|
|
554
|
+
*
|
|
555
|
+
* The issuer identifier is syntax-validated (absolute http/https URL without
|
|
556
|
+
* userinfo, query, or fragment) but otherwise preserved exactly as configured
|
|
557
|
+
* after surrounding-whitespace trimming: no trailing slash is added and path
|
|
558
|
+
* variants such as `/tenant`, `/tenant/`, and `/tenant//` remain distinct.
|
|
559
|
+
* Endpoint URLs are normalized separately with `URL.toString()`.
|
|
280
560
|
*/
|
|
281
561
|
declare function resolveOidcVaultConfig(config?: OidcVaultConfig): OidcVaultResolvedConfig;
|
|
282
562
|
/**
|
|
@@ -303,7 +583,18 @@ declare function createOidcVaultJwtAccessTokenValidator(options: OidcVaultJwtAcc
|
|
|
303
583
|
declare function normalizeOidcVaultBasePath(value?: string): string;
|
|
304
584
|
/**
|
|
305
585
|
* Create the core OIDC vault middleware.
|
|
586
|
+
*
|
|
587
|
+
* Construction takes an internal resolved snapshot of `options` without
|
|
588
|
+
* mutating the caller object: normalized values (such as
|
|
589
|
+
* `frontendRedirectUri`) are stored on the snapshot, plain-data containers
|
|
590
|
+
* (`cookie`, `trustedOrigins`, `config`) are shallow-copied, and service
|
|
591
|
+
* references (`storeProvider`, `hooks`, `tokenIssuer`, `now`) are retained
|
|
592
|
+
* by reference, never deep-cloned. Mutating or replacing the caller options
|
|
593
|
+
* after this call has no effect on the created router. Post-commit hooks
|
|
594
|
+
* (`onSessionCreated`, `onSessionRefreshed`, `onLogout`) are notifications
|
|
595
|
+
* whose failures are reported to `onError` without undoing committed state;
|
|
596
|
+
* other hooks run pre-commit and can veto the operation by throwing.
|
|
306
597
|
*/
|
|
307
598
|
declare function createOidcVaultMiddleware(options: OidcVaultOptions): Router;
|
|
308
599
|
|
|
309
|
-
export { type AuthorizationTransaction, type AuthorizationTransactionInput, type ConsumeBackchannelLogoutTokenJtiInput, DEFAULT_AUTHORIZATION_TRANSACTION_TTL_MS, DEFAULT_EXCHANGE_CODE_TTL_MS, DEFAULT_OIDC_SCOPES, DEFAULT_OIDC_VAULT_BASE_PATH, DEFAULT_OIDC_VAULT_REQUEST_BODY_LIMIT, type DeleteSessionsByLogicalSessionIdInput, type DeleteSessionsByProviderSessionIdInput, type DeleteSessionsBySubjectInput, type ExchangeCodeRecord, type ExchangeCodeRecordInput, type IssueTokenInput, OIDC_VAULT_ROUTE_PATHS, OIDC_VAULT_URL_ENCODED_PARAMETER_LIMIT, type OidcVaultAccessTokenMiddlewareOptions, type OidcVaultAccessTokenValidationResult, type OidcVaultAccessTokenValidator, type OidcVaultAuthContext, type OidcVaultAuthenticatedRequest, type OidcVaultBackchannelLogoutResult, type OidcVaultConfig, type OidcVaultConfigMode, type OidcVaultCookieDeploymentMode, type OidcVaultCookieOptions, type OidcVaultCookieSameSite, type OidcVaultEnv, type OidcVaultErrorContext, type OidcVaultExchangeResult, type OidcVaultHookContext, type OidcVaultHooks, type OidcVaultJwtAccessTokenValidatorOptions, type OidcVaultLogoutResult, type OidcVaultOptions, type OidcVaultProviderMetadata, type OidcVaultResolvedConfig, type OidcVaultRouteName, type OidcVaultSession, type OidcVaultSessionInput, type OidcVaultSessionTransport, OidcVaultStoreConflictError, type OidcVaultStoreProvider, type OidcVaultTokenIssueResult, type OidcVaultTokenIssuer, type OidcVaultUserProfile, type RotateSessionInput, createOidcVaultAccessTokenMiddleware, createOidcVaultJwtAccessTokenValidator, createOidcVaultMiddleware, normalizeOidcVaultBasePath, resolveOidcVaultConfig, resolveOidcVaultConfigFromEnv };
|
|
600
|
+
export { type AuthorizationTransaction, type AuthorizationTransactionInput, type ConsumeBackchannelLogoutTokenJtiInput, DEFAULT_AUTHORIZATION_TRANSACTION_TTL_MS, DEFAULT_EXCHANGE_CODE_TTL_MS, DEFAULT_OIDC_SCOPES, DEFAULT_OIDC_VAULT_BASE_PATH, DEFAULT_OIDC_VAULT_REQUEST_BODY_LIMIT, type DeleteSessionsByLogicalSessionIdInput, type DeleteSessionsByProviderSessionIdInput, type DeleteSessionsBySubjectInput, type ExchangeCodeRecord, type ExchangeCodeRecordInput, type IssueTokenInput, OIDC_VAULT_ROUTE_PATHS, OIDC_VAULT_URL_ENCODED_PARAMETER_LIMIT, type OidcVaultAccessTokenMiddlewareErrorContext, type OidcVaultAccessTokenMiddlewareOptions, type OidcVaultAccessTokenValidationResult, type OidcVaultAccessTokenValidator, type OidcVaultAuthContext, type OidcVaultAuthenticatedRequest, type OidcVaultBackchannelLogoutResult, type OidcVaultConfig, type OidcVaultConfigMode, type OidcVaultCookieDeploymentMode, type OidcVaultCookieOptions, type OidcVaultCookieSameSite, type OidcVaultEnv, type OidcVaultErrorContext, type OidcVaultExchangeResult, type OidcVaultHookContext, type OidcVaultHooks, type OidcVaultJwtAccessTokenValidatorOptions, type OidcVaultLogoutResult, type OidcVaultOptions, type OidcVaultProviderMetadata, type OidcVaultResolvedConfig, type OidcVaultRouteName, type OidcVaultSession, type OidcVaultSessionInput, type OidcVaultSessionTransport, OidcVaultStoreConflictError, type OidcVaultStoreProvider, type OidcVaultTokenIssueResult, type OidcVaultTokenIssuer, type OidcVaultUserProfile, type RotateSessionInput, createOidcVaultAccessTokenMiddleware, createOidcVaultJwtAccessTokenValidator, createOidcVaultMiddleware, normalizeOidcVaultBasePath, resolveOidcVaultConfig, resolveOidcVaultConfigFromEnv };
|