@web-ts-toolkit/express-oidc-vault 0.47.1 → 0.49.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.
Files changed (6) hide show
  1. package/README.md +994 -75
  2. package/index.d.mts +423 -32
  3. package/index.d.ts +423 -32
  4. package/index.js +1972 -390
  5. package/index.mjs +1965 -384
  6. package/package.json +5 -3
package/index.d.mts CHANGED
@@ -3,6 +3,97 @@ import { KeyObject } from 'node:crypto';
3
3
  import { JWK } from 'jose';
4
4
 
5
5
  type OidcVaultRouteName = 'login' | 'callback' | 'exchange' | 'refresh' | 'logout' | 'backchannel-logout';
6
+ /** Enabling the option defaults to `optional`; omitting it keeps bearer behavior. */
7
+ type OidcVaultDeviceBindingMode = 'optional' | 'required';
8
+ /** DPoP proof algorithms, independent of the app-local access token's signing algorithm. */
9
+ type OidcVaultDpopAlgorithm = 'ES256' | 'PS256' | 'RS256';
10
+ /**
11
+ * Immutable persisted sender constraint. `jkt` is the canonical RFC 7638
12
+ * SHA-256 JWK thumbprint (43 base64url characters). Store no JWK, private key,
13
+ * proof algorithm, or historical enforcement mode in this record.
14
+ */
15
+ interface OidcVaultDpopBinding {
16
+ type: 'dpop';
17
+ jkt: string;
18
+ }
19
+ /** Verified request context; `alg` is checked against the current proof policy. */
20
+ interface OidcVaultVerifiedDpopBinding extends OidcVaultDpopBinding {
21
+ alg: OidcVaultDpopAlgorithm;
22
+ }
23
+ /**
24
+ * Optional stateless, key/context-bound DPoP nonce policy. Challenges are issued
25
+ * only after other proof/target checks and before replay reservation. Any
26
+ * authentic live nonce permits parallel fresh proofs; it does not replace the
27
+ * normal iat window or single-use JTI reservation. Shared instances need the
28
+ * same secret; rotation requires a new challenge, with no previous-secret list.
29
+ */
30
+ interface OidcVaultDpopNonceOptions {
31
+ /** Shared random secret of at least 32 bytes, copied at construction. */
32
+ secret: Uint8Array;
33
+ /** Integer lifetime in seconds, 1–300; default 60. */
34
+ lifetimeSeconds?: number;
35
+ }
36
+ /**
37
+ * Shared RFC 9449 proof profile for vault POSTs and request-aware APIs.
38
+ * Proofs are limited to 8192 wire bytes and 2048 decoded protected-header/JWK
39
+ * bytes, use typ dpop+jwt and public-only asymmetric keys, and require exact
40
+ * method/pinned normalized URL plus a signed printable ASCII JTI (1–128 bytes).
41
+ * Signature verification precedes claims; strict iat validity is
42
+ * nowSeconds - age - skew < iat <= nowSeconds + skew. APIs additionally match
43
+ * original verified cnf.jkt and SHA-256 ath of the ASCII access token.
44
+ */
45
+ interface OidcVaultDpopProofOptions {
46
+ /** Nonempty asymmetric allowlist; default `['ES256']` (P-256). RSA proofs require 2048–4096 bits. */
47
+ algorithms?: readonly OidcVaultDpopAlgorithm[];
48
+ /** Integer maximum proof age in seconds, 1–300; default 60. */
49
+ proofMaxAgeSeconds?: number;
50
+ /** Integer clock tolerance in seconds, 0–30; default 5. */
51
+ clockSkewSeconds?: number;
52
+ /** Off by default. Challenges are at most 512 bytes; retry once with a fresh proof, never reuse its JTI. */
53
+ nonce?: false | OidcVaultDpopNonceOptions;
54
+ }
55
+ /**
56
+ * Opt-in sender constraint. `optional` permits legacy unbound records without
57
+ * enrolling them from a later proof; `required` rejects unbound use. Persisted
58
+ * bound records never downgrade when the option or a proof is omitted.
59
+ */
60
+ interface OidcVaultDeviceBindingOptions extends OidcVaultDpopProofOptions {
61
+ /** Default optional when configured. Required rejects unbound use; there is no legacy downgrade switch. */
62
+ mode?: OidcVaultDeviceBindingMode;
63
+ }
64
+ /**
65
+ * Opt-in, vendor-independent browser recognition/change detection, NOT proof of
66
+ * possession. A copyable signal never satisfies required DPoP or constrains API
67
+ * access. POST login alone enrolls a supplied signal; absence is intentionally
68
+ * unenrolled. Callback stores only SHA-256 in reserved session metadata.
69
+ */
70
+ interface OidcVaultFingerprintRecognitionOptions {
71
+ /**
72
+ * HTTP field name; default X-Device-Fingerprint. Must not collide with auth,
73
+ * cookie, origin, content, or transport headers. One raw field with a nonempty
74
+ * printable ASCII value, at most 256 bytes; no trimming or normalization.
75
+ * Malformed/duplicate/oversized opted-in signals return 400
76
+ * OIDC_VAULT_INVALID_FINGERPRINT before credential work.
77
+ */
78
+ headerName?: string;
79
+ }
80
+ /**
81
+ * Request-aware API sender constraint. Every API accepting bound JWTs must
82
+ * enforce this policy; signature-only validation does not prove possession.
83
+ * Construction snapshots plain options, URLs, algorithms and nonce bytes.
84
+ */
85
+ interface OidcVaultApiDeviceBindingOptions extends OidcVaultDeviceBindingOptions {
86
+ /** Static HTTPS origin (loopback HTTP development allowed); never derived from Host/proxy headers. */
87
+ publicOrigin: string;
88
+ /** External mount prefix stripped by a proxy, normalized at construction; default empty. No query/fragment. */
89
+ publicPathPrefix?: string;
90
+ /** Shared static printable ASCII protection-space label, 1–128 bytes; never a token, route or instance ID. */
91
+ replayNamespace: string;
92
+ /** Explicit shared atomic service, normally the vault store. No per-middleware fallback. */
93
+ replayStore: OidcVaultDpopReplayStore;
94
+ /** Epoch-millisecond clock for proof age/nonce/replay; default Date.now. Shared instances need synchronized clocks. */
95
+ now?: () => number;
96
+ }
6
97
  interface OidcVaultUserProfile {
7
98
  sub: string;
8
99
  email?: string;
@@ -11,15 +102,19 @@ interface OidcVaultUserProfile {
11
102
  [key: string]: unknown;
12
103
  }
13
104
  /**
14
- * Stored session identity. Exchange, refresh, and live-session logout compare
15
- * each defined field verbatim against resolved middleware config before use.
105
+ * Stored session identity. Exchange, refresh, and logout compare each defined
106
+ * field verbatim against resolved middleware config before use. Opt-in/guarded
107
+ * exchange checks before code consumption; built-in logout also checks the
108
+ * surviving lineage through unexpired aliases before proof or deletion.
16
109
  * Known mismatches fail with 401 `OIDC_VAULT_INVALID_SESSION` without changing
17
110
  * the session or cookie. Issuer trailing-slash variants are distinct.
18
111
  *
19
112
  * 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.
113
+ * Use separate session/alias, exchange-code, and transaction namespaces for
114
+ * complete isolation. Disabled legacy bearer exchange retains its historical
115
+ * consume-before-identity ordering; old custom bearer stores without revocation
116
+ * context retain their legacy alias behavior. Missing identifiers are not an
117
+ * isolation guarantee.
23
118
  */
24
119
  interface OidcVaultProviderMetadata {
25
120
  issuer?: string;
@@ -36,6 +131,8 @@ interface OidcVaultSession {
36
131
  subject: string;
37
132
  providerSessionId?: string;
38
133
  provider?: OidcVaultProviderMetadata;
134
+ /** Original login-selected sender constraint, enforced before exchange/refresh/logout (including aliases); never enrolled by a later proof. */
135
+ deviceBinding?: OidcVaultDpopBinding;
39
136
  refreshToken: string;
40
137
  idToken: string;
41
138
  accessToken?: string;
@@ -70,6 +167,11 @@ interface OidcVaultSession {
70
167
  * serialization round-trips, so callers must not rely on object identity,
71
168
  * custom prototypes, functions, symbols, Dates, Maps, Sets, undefined object
72
169
  * properties, or other runtime-only values surviving persistence.
170
+ * `oidcVaultFingerprintRecognition` is reserved: `{ version: 1, hash }` is
171
+ * immutable login-selected SHA-256 recognition evidence, never raw signal
172
+ * data. Core preserves it through callback/refresh and removes it from token
173
+ * issuer input and public profiles/responses. Disclose collection/retention;
174
+ * it lasts with the transaction/session, not the local access-token lifetime.
73
175
  */
74
176
  metadata?: Record<string, unknown>;
75
177
  }
@@ -79,9 +181,19 @@ interface AuthorizationTransactionInput {
79
181
  pkceVerifier: string;
80
182
  codeChallenge: string;
81
183
  returnTo?: string;
184
+ /** Login-selected sender constraint, never reconstructed from a later proof. */
185
+ deviceBinding?: OidcVaultDpopBinding;
186
+ /** SHA-256 hash of the temporary HttpOnly browser-binding cookie; never store the cookie secret. */
187
+ browserBindingHash?: string;
82
188
  createdAt: number;
83
189
  expiresAt: number;
84
- /** See `OidcVaultSession.metadata` for the portable metadata value domain. */
190
+ /**
191
+ * See `OidcVaultSession.metadata` for the portable value domain. POST login
192
+ * reserves `oidcVaultTransactionProvider` for its resolved issuer/clientId;
193
+ * stores must preserve it for callback identity preflight. Opted-in POST login
194
+ * also carries immutable `oidcVaultFingerprintRecognition` for callback
195
+ * session creation; no raw fingerprint signal is stored.
196
+ */
85
197
  metadata?: Record<string, unknown>;
86
198
  }
87
199
  type AuthorizationTransaction = AuthorizationTransactionInput;
@@ -89,6 +201,10 @@ interface ExchangeCodeRecordInput {
89
201
  code: string;
90
202
  sessionId: string;
91
203
  returnTo?: string;
204
+ /** Copied from the authenticated login transaction; must agree with the session. */
205
+ deviceBinding?: OidcVaultDpopBinding;
206
+ /** Copied transaction-cookie hash; guarded exchange matches both cookie and key. */
207
+ browserBindingHash?: string;
92
208
  createdAt: number;
93
209
  expiresAt: number;
94
210
  }
@@ -99,6 +215,7 @@ interface OidcVaultSessionInput extends Omit<OidcVaultSession, 'createdAt' | 'up
99
215
  }
100
216
  interface RotateSessionInput {
101
217
  sessionId: string;
218
+ /** Omitted binding inherits the source; changing its key or enrolling an unbound source is rejected. */
102
219
  nextSession: OidcVaultSession;
103
220
  }
104
221
  interface DeleteSessionsBySubjectInput {
@@ -119,9 +236,72 @@ interface ConsumeBackchannelLogoutTokenJtiInput {
119
236
  /** Finite future epoch-millisecond expiry. Values `<= now` are expired. */
120
237
  expiresAt: number;
121
238
  }
239
+ /**
240
+ * Complete guarded-record match. Explicit `null` requires an absent/undefined
241
+ * stored field; it never means ignore the field. Both fields are mandatory.
242
+ * Valid persisted shapes are legacy (neither field), cookie-only (hash), or
243
+ * bound (hash + key). Stored null/malformed fields and a key without a hash
244
+ * are invalid. Both hashes use canonical 43-character SHA-256 base64url.
245
+ */
246
+ interface OidcVaultRecordBindingMatch {
247
+ deviceBinding: OidcVaultDpopBinding | null;
248
+ browserBindingHash: string | null;
249
+ }
250
+ interface ConsumeAuthorizationTransactionIfMatchesInput {
251
+ state: string;
252
+ match: OidcVaultRecordBindingMatch;
253
+ }
254
+ interface ConsumeExchangeCodeIfMatchesInput {
255
+ code: string;
256
+ /** Session ID from preflight, included in the atomic consume comparison. */
257
+ expectedSessionId: string;
258
+ match: OidcVaultRecordBindingMatch;
259
+ }
260
+ interface ReserveDpopProofInput {
261
+ /** Opaque `dpop:v1:` + SHA-256 base64url of JSON([effectiveNamespace, jkt, jti]), supplied after proof/target/nonce checks. */
262
+ replayKey: string;
263
+ /** Future safe-integer epoch milliseconds; maximum remaining TTL 360000 ms. */
264
+ expiresAt: number;
265
+ }
266
+ /**
267
+ * Shared atomic per-request replay admission; no implicit per-core-instance
268
+ * memory fallback. Independent memory-store objects are not shared protection.
269
+ * Shared instances need identical protection spaces/proof windows and synchronized
270
+ * clocks. Never release a reservation after a later route/issuer failure.
271
+ */
272
+ interface OidcVaultDpopReplayStore {
273
+ /**
274
+ * Reserve once through expiry. Duplicate/invalid/expired input returns false
275
+ * without extending expiry or allocating state. Capacity/provider failures
276
+ * throw; callers must fail closed, never evict live reservations. Built-ins
277
+ * default to 100000 entries per shared namespace. Expired entries awaiting
278
+ * bounded cleanup may conservatively occupy capacity. Duplicate detection
279
+ * precedes capacity rejection; capacity throws `OidcVaultDpopReplayCapacityError`.
280
+ */
281
+ reserveDpopProof(input: ReserveDpopProofInput): Promise<boolean>;
282
+ }
283
+ /**
284
+ * Detached revocation authority for a currently live lineage, resolved through
285
+ * a live handle or unexpired rotation alias. Never authenticates an alias and
286
+ * contains no tokens, profile, metadata, or provider fields beyond issuer/clientId.
287
+ * Inconsistent/malformed lineage binding or identity throws a private diagnostic.
288
+ */
289
+ interface OidcVaultSessionRevocationContext {
290
+ logicalSessionId: string;
291
+ provider?: OidcVaultProviderMetadata;
292
+ deviceBinding?: OidcVaultDpopBinding;
293
+ }
122
294
  declare class OidcVaultStoreConflictError extends Error {
123
295
  constructor(message?: string);
124
296
  }
297
+ /**
298
+ * Shared DPoP replay capacity is exhausted. No live reservation is evicted and
299
+ * no proof is admitted without replay state. Handle like any replay-store
300
+ * failure: fail closed; expose only the sanitized replay-unavailable error.
301
+ */
302
+ declare class OidcVaultDpopReplayCapacityError extends Error {
303
+ constructor(message?: string);
304
+ }
125
305
  /**
126
306
  * Portable store boundary for JSON-compatible plain objects/arrays and scalar
127
307
  * values (strings, finite numbers, booleans, null). Built-in providers capture
@@ -140,10 +320,20 @@ declare class OidcVaultStoreConflictError extends Error {
140
320
  interface OidcVaultStoreProvider {
141
321
  /** Upsert an authorization transaction by `state`. */
142
322
  createAuthorizationTransaction(input: AuthorizationTransactionInput): Promise<void>;
323
+ /** Legacy consume: refuses guarded (cookie/key-bound) records without consuming them. */
143
324
  consumeAuthorizationTransaction(state: string): Promise<AuthorizationTransaction | null>;
325
+ /** Optional opt-in capability: detached live preflight snapshot, not a lock. */
326
+ getAuthorizationTransaction?(state: string): Promise<AuthorizationTransaction | null>;
327
+ /** Optional opt-in capability: atomic expiry + complete exact/null match + consume; mismatch leaves the record live. */
328
+ consumeAuthorizationTransactionIfMatches?(input: ConsumeAuthorizationTransactionIfMatchesInput): Promise<AuthorizationTransaction | null>;
144
329
  /** Upsert an exchange code record by `code`. */
145
330
  createExchangeCode(input: ExchangeCodeRecordInput): Promise<void>;
331
+ /** Legacy consume: refuses guarded (cookie/key-bound) records without consuming them. */
146
332
  consumeExchangeCode(code: string): Promise<ExchangeCodeRecord | null>;
333
+ /** Optional opt-in capability: detached live preflight snapshot, not a lock. */
334
+ getExchangeCode?(code: string): Promise<ExchangeCodeRecord | null>;
335
+ /** Optional opt-in capability: atomically match the session ID and both binding fields before consuming. */
336
+ consumeExchangeCodeIfMatches?(input: ConsumeExchangeCodeIfMatchesInput): Promise<ExchangeCodeRecord | null>;
147
337
  /**
148
338
  * Create a session by `sessionId`, defaulting timestamps and logical lineage when omitted.
149
339
  *
@@ -166,12 +356,19 @@ interface OidcVaultStoreProvider {
166
356
  */
167
357
  createSession(input: OidcVaultSessionInput): Promise<OidcVaultSession>;
168
358
  getSession(sessionId: string): Promise<OidcVaultSession | null>;
359
+ /** Optional opt-in capability: resolve only a currently live lineage, including through unexpired aliases. No upstream tokens. */
360
+ getSessionRevocationContext?(sessionId: string): Promise<OidcVaultSessionRevocationContext | null>;
361
+ /** Optional opt-in capability; see `OidcVaultDpopReplayStore.reserveDpopProof`. */
362
+ reserveDpopProof?(input: ReserveDpopProofInput): Promise<boolean>;
169
363
  /**
170
364
  * Atomically replace an existing session with a distinct unused `nextSession.sessionId`.
171
365
  *
172
366
  * Providers preserve the existing logical session ID when the next session omits
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
367
+ * one, inherit the original device binding when omitted, and reject changing
368
+ * a bound key or adding binding to an unbound source without mutation. Null or
369
+ * malformed security fields are invalid, never legacy. Retain the old public
370
+ * session ID as an in-flight-request revocation alias. Rotation itself does
371
+ * not revoke the lineage. Providers throw
175
372
  * `OidcVaultStoreConflictError` without changing source or target data when
176
373
  * the source is missing, the target already exists, or the target ID equals
177
374
  * the source ID.
@@ -220,6 +417,28 @@ interface OidcVaultStoreProvider {
220
417
  /** Delete matching provider-session IDs, filtering by each supplied issuer/client; string input is unscoped. */
221
418
  deleteSessionsByProviderSessionId(input: string | DeleteSessionsByProviderSessionIdInput): Promise<number>;
222
419
  }
420
+ /**
421
+ * Required store capabilities for opt-in device binding or fingerprint
422
+ * recognition. All six methods are checked at vault construction, including
423
+ * fingerprint-only flows (which do not reserve DPoP proofs). Old bearer-only
424
+ * custom stores retain the base interface. Guarded reads are preflight only:
425
+ * providers must compare/consume atomically and preserve original binding and
426
+ * portable reserved recognition metadata through core's rotation inputs.
427
+ */
428
+ interface OidcVaultDeviceBindingStoreProvider extends OidcVaultStoreProvider, OidcVaultDpopReplayStore {
429
+ /** Detached live snapshot, never a lock. Malformed/null binding/hash is invalid, not legacy. */
430
+ getAuthorizationTransaction(state: string): Promise<AuthorizationTransaction | null>;
431
+ /** Atomic expiry + full exact/null match + deletion. Mismatch leaves the live record available for an honest retry. */
432
+ consumeAuthorizationTransactionIfMatches(input: ConsumeAuthorizationTransactionIfMatchesInput): Promise<AuthorizationTransaction | null>;
433
+ /** Detached live preflight snapshot, without spending the code. */
434
+ getExchangeCode(code: string): Promise<ExchangeCodeRecord | null>;
435
+ /** Atomic expiry + expectedSessionId + both exact/null binding fields + deletion; no get/unconditional-delete fallback. */
436
+ consumeExchangeCodeIfMatches(input: ConsumeExchangeCodeIfMatchesInput): Promise<ExchangeCodeRecord | null>;
437
+ /** Resolve current lineage authority, never the alias's missing/historical binding; no credentials are returned. */
438
+ getSessionRevocationContext(sessionId: string): Promise<OidcVaultSessionRevocationContext | null>;
439
+ /** Atomic duplicate-first admission; false rejects the proof, capacity/provider errors fail closed with HTTP 503. */
440
+ reserveDpopProof(input: ReserveDpopProofInput): Promise<boolean>;
441
+ }
223
442
  interface OidcVaultHookContext {
224
443
  route: OidcVaultRouteName;
225
444
  req: Request;
@@ -230,7 +449,7 @@ interface OidcVaultHookContext {
230
449
  interface OidcVaultErrorContext extends OidcVaultHookContext {
231
450
  /**
232
451
  * Original private diagnostic, separate from sanitized browser JSON. Narrow
233
- * before use; provider transport errors retain the original failure in
452
+ * before use; provider transport/replay admission errors retain the original failure in
234
453
  * `error.cause`, while issuer-result validation supplies a TypeError directly.
235
454
  */
236
455
  error: unknown;
@@ -246,18 +465,34 @@ interface OidcVaultHooks {
246
465
  * After this hook, a valid earlier epoch-millisecond expiry is preserved;
247
466
  * removal, extension, or an invalid timestamp restores the configured cap.
248
467
  * Without `sessionTtlMs`, application/store lifetime policy is unchanged.
468
+ * Security-owned `deviceBinding` is restored from core's private snapshot;
469
+ * the hook cannot enroll, remove, or rebind a sender constraint. Guarded POST
470
+ * callbacks also retain their fresh session/lineage IDs and resolved provider
471
+ * identity independently of hook mutations. Reserved fingerprint recognition
472
+ * metadata is restored from the original transaction, including unenrolled
473
+ * absence; a hook/profile cannot enroll, strip, or rebind it. Other application
474
+ * metadata/profile fields remain mutable; throwing is an authenticated terminal veto.
249
475
  */
250
476
  onBeforeSessionCreate?(context: OidcVaultHookContext): void | Promise<void>;
251
477
  onSessionCreated?(context: OidcVaultHookContext): void | Promise<void>;
478
+ /** Post-rotation notification with owned plain session data; mutation cannot change stored/response authority or profile precedence. */
252
479
  onSessionRefreshed?(context: OidcVaultHookContext): void | Promise<void>;
480
+ /** Pre-revocation veto for a live handle, after identity/proof/nonce/replay. Receives owned session data; deletion uses original lineage authority. */
253
481
  onBeforeLogout?(context: OidcVaultHookContext): void | Promise<void>;
254
482
  onLogout?(context: OidcVaultHookContext): void | Promise<void>;
255
483
  onError?(context: OidcVaultErrorContext): void | Promise<void>;
256
484
  }
257
485
  interface IssueTokenInput {
486
+ /** Owned session data; reserved fingerprint recognition evidence is omitted to keep hashes out of application tokens. */
258
487
  session: OidcVaultSession;
259
488
  req: Request;
260
489
  res: Response;
490
+ /**
491
+ * Authoritative verified request/key context, detached and frozen by core.
492
+ * Use this thumbprint for `cnf.jkt`, not mutable session/profile fields.
493
+ * Absent for unbound issuance; a later proof never enrolls a legacy session.
494
+ */
495
+ deviceBinding?: Readonly<OidcVaultVerifiedDpopBinding>;
261
496
  }
262
497
  /**
263
498
  * Local application credentials returned by `OidcVaultTokenIssuer.issue`.
@@ -265,18 +500,19 @@ interface IssueTokenInput {
265
500
  * properties are ignored and cannot override the response's session ID/user.
266
501
  */
267
502
  interface OidcVaultTokenIssueResult {
268
- /** Nonempty opaque token string, returned verbatim without trimming. */
503
+ /** Nonempty opaque token for unbound issuance; bound issuance requires a compact signed JWT with matching `cnf.jkt`. */
269
504
  accessToken: string;
270
505
  /** Token lifetime in seconds: a finite, nonnegative safe integer (zero is valid). */
271
506
  expiresIn: number;
272
- /** Optional exact literal `Bearer`; omitted/undefined stays absent in JSON. */
273
- tokenType?: 'Bearer';
507
+ /** Exact `DPoP` is required when bound. Unbound permits only `Bearer` or omission; omitted/undefined stays absent in JSON. */
508
+ tokenType?: 'Bearer' | 'DPoP';
274
509
  }
275
510
  /**
276
511
  * Trusted application token issuer for exchange and refresh. Return a non-null,
277
512
  * non-array object satisfying `OidcVaultTokenIssueResult`; only its declared
278
513
  * credential fields enter the response. This contains accidental extensions,
279
- * not arbitrary behavior of trusted issuers/hooks with session/request/response access.
514
+ * not arbitrary behavior of trusted issuers/hooks with request/response access.
515
+ * Core retains its own binding/lineage snapshots across issuer calls.
280
516
  */
281
517
  interface OidcVaultTokenIssuer {
282
518
  /**
@@ -284,6 +520,8 @@ interface OidcVaultTokenIssuer {
284
520
  * (including the rotated refresh session), clear a cookie-transport session
285
521
  * cookie, and return sanitized HTTP 500 / `OIDC_VAULT_INTERNAL_ERROR`.
286
522
  * Field diagnostics are available privately through `hooks.onError`.
523
+ * Core decodes a bound result only to check this trusted issuer contract;
524
+ * APIs must independently verify signature, issuer, audience, and expiry.
287
525
  */
288
526
  issue(input: IssueTokenInput): Promise<OidcVaultTokenIssueResult>;
289
527
  }
@@ -292,12 +530,40 @@ interface OidcVaultAccessTokenValidationResult {
292
530
  sessionId?: string;
293
531
  scope?: string;
294
532
  claims?: Record<string, unknown>;
533
+ /** Verified sender constraint. Legacy adapters may omit it only for genuinely unbound credentials. */
534
+ confirmation?: OidcVaultAccessTokenConfirmation | null;
535
+ }
536
+ /** Canonical RFC 7638 SHA-256 thumbprint derived from verified token/introspection data, never from a proof alone. */
537
+ interface OidcVaultAccessTokenConfirmation {
538
+ jkt: string;
539
+ }
540
+ interface OidcVaultAccessTokenRequestInput {
541
+ token: string;
542
+ scheme: 'Bearer' | 'DPoP';
543
+ req: Request;
544
+ }
545
+ /** Mandatory confirmation: null means verified unbound; missing confirmation or malformed/unsupported cnf is invalid. */
546
+ interface OidcVaultRequestAwareAccessTokenValidationResult extends OidcVaultAccessTokenValidationResult {
547
+ confirmation: OidcVaultAccessTokenConfirmation | null;
295
548
  }
296
549
  interface OidcVaultAuthContext extends OidcVaultAccessTokenValidationResult {
297
550
  token: string;
551
+ /** Present only after original-key proof, API ath, nonce and shared replay admission all pass. */
552
+ deviceBinding?: Readonly<OidcVaultVerifiedDpopBinding>;
298
553
  }
299
554
  interface OidcVaultAccessTokenValidator {
555
+ /** Binding-disabled middleware invokes exactly validate(token), with one argument. Report any known confirmation. */
300
556
  validate(token: string): Promise<OidcVaultAccessTokenValidationResult>;
557
+ /** Required at middleware construction when deviceBinding is enabled; called for both Bearer and DPoP. */
558
+ validateWithRequest?(input: OidcVaultAccessTokenRequestInput): Promise<OidcVaultRequestAwareAccessTokenValidationResult>;
559
+ }
560
+ /**
561
+ * Trusted adapter for verified JWT/introspection data. Faithfully report the
562
+ * original confirmation independently of custom mapping: null is genuinely
563
+ * unbound, never a malformed/unsupported cnf. The middleware owns proof checks.
564
+ */
565
+ interface OidcVaultRequestAwareAccessTokenValidator extends OidcVaultAccessTokenValidator {
566
+ validateWithRequest(input: OidcVaultAccessTokenRequestInput): Promise<OidcVaultRequestAwareAccessTokenValidationResult>;
301
567
  }
302
568
  interface OidcVaultAccessTokenMiddlewareErrorContext {
303
569
  error: unknown;
@@ -308,16 +574,20 @@ interface OidcVaultAccessTokenMiddlewareErrorContext {
308
574
  }
309
575
  interface OidcVaultAccessTokenMiddlewareOptions {
310
576
  validator: OidcVaultAccessTokenValidator;
577
+ /** Opt-in API DPoP enforcement; requires validateWithRequest. Omission preserves the one-argument legacy path. */
578
+ deviceBinding?: OidcVaultApiDeviceBindingOptions;
311
579
  /**
312
580
  * Pre-`next()` veto hook, not a post-commit notification: when it throws,
313
581
  * 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
582
+ * error response is sent. A valid credential plus a failing hook
583
+ * never surfaces as an invalid-token 401: a controlled package error from the
584
+ * hook keeps its own status/code/client message (a 401 uses the attempted
585
+ * scheme's challenge, other statuses carry no challenge), while any other hook
318
586
  * error becomes a sanitized `500 OIDC_VAULT_AUTH_CONTEXT_FAILED` without
319
587
  * leaking the original message. The original error is observable via
320
- * `onError` for private server-side logs.
588
+ * `onError` for private server-side logs. Security-owned token/confirmation/
589
+ * deviceBinding and req.auth authority are restored after mutable hooks;
590
+ * a veto never releases an admitted proof's replay reservation.
321
591
  */
322
592
  onAuthContext?(input: {
323
593
  req: Request;
@@ -325,21 +595,25 @@ interface OidcVaultAccessTokenMiddlewareOptions {
325
595
  auth: OidcVaultAuthContext;
326
596
  }): void | Promise<void>;
327
597
  /**
328
- * Observes the original error for every bearer-middleware failure
329
- * (extraction, validator, and `onAuthContext` failures) without affecting
598
+ * Observes the original error for every API-middleware failure
599
+ * (extraction, validator, proof/nonce/replay, and `onAuthContext`) without affecting
330
600
  * the sanitized client response. Failures thrown by this observer are
331
- * swallowed so the original error response is preserved.
601
+ * swallowed so the original error response is preserved. Replay failures
602
+ * retain the provider diagnostic in non-enumerable error.cause. No request
603
+ * auth context is attached before proof acceptance or after a veto.
332
604
  */
333
605
  onError?(context: OidcVaultAccessTokenMiddlewareErrorContext): void | Promise<void>;
334
606
  }
335
607
  interface OidcVaultAuthenticatedRequest extends Request {
336
608
  auth?: OidcVaultAuthContext;
337
609
  }
610
+ /** Local JWT verification options, independent of the asymmetric DPoP proof policy; captured at construction. */
338
611
  interface OidcVaultJwtAccessTokenValidatorOptions {
339
612
  key: CryptoKey | KeyObject | JWK | Uint8Array;
340
613
  issuer?: string;
341
614
  audience?: string | string[];
342
615
  algorithms?: string[];
616
+ /** Verified cnf is snapshotted before this mapper; mapper-supplied confirmation/deviceBinding is ignored. */
343
617
  mapClaims?(claims: Record<string, unknown>): OidcVaultAccessTokenValidationResult;
344
618
  }
345
619
  declare module 'express-serve-static-core' {
@@ -373,11 +647,15 @@ interface OidcVaultConfig {
373
647
  }
374
648
  interface OidcVaultLogoutResult {
375
649
  /**
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.
650
+ * Successful logout commits revocation before upstream work and clears the
651
+ * session cookie under cookie transport. Built-in live handles and unexpired
652
+ * aliases authenticate the surviving lineage's provider/original binding;
653
+ * wrong identity, missing/wrong/stale/replayed proof, or disabled acceptance
654
+ * of a bound lineage fails without deleting or clearing. No currently live
655
+ * target is idempotent success without deletion or proof reservation. Aliases
656
+ * grant revocation only, not refresh authentication or upstream redirects.
657
+ * Old custom bearer stores without revocation context retain legacy alias
658
+ * deletion behavior. Stateless application access tokens are not invalidated.
381
659
  * Local-only logout (`redirect` unset or `false`) never contacts the provider.
382
660
  * Redirected logout (`redirect: true`)
383
661
  * treats the upstream end-session redirect as best-effort: when provider
@@ -397,9 +675,38 @@ interface OidcVaultExchangeResult extends Partial<OidcVaultTokenIssueResult> {
397
675
  /** Session profile; extra token-issuer result properties cannot override it. */
398
676
  user?: OidcVaultUserProfile;
399
677
  }
678
+ /** JSON body for opt-in `POST <basePath>/login`; proof/key and recognition signals belong in their configured headers, not the body. */
679
+ interface OidcVaultLoginInitiationInput {
680
+ /** Optional destination on the configured frontend origin. Query-string returnTo is ignored by POST login. */
681
+ returnTo?: string;
682
+ }
683
+ /**
684
+ * Exact successful POST-login JSON. Navigate to this URL after storing a proof
685
+ * key when DPoP is enabled. Use credentials: 'include' even with body session
686
+ * transport: initiation sets a temporary HttpOnly transaction cookie.
687
+ */
688
+ interface OidcVaultLoginInitiationResult {
689
+ authorizationUrl: string;
690
+ }
400
691
  type OidcVaultSessionTransport = 'body' | 'cookie';
401
692
  type OidcVaultCookieDeploymentMode = 'same-origin' | 'same-site' | 'cross-site';
402
693
  type OidcVaultCookieSameSite = 'lax' | 'strict' | 'none';
694
+ /**
695
+ * Temporary browser-binding cookie for POST login -> headerless callback ->
696
+ * guarded exchange. Always host-only, Path=/, HttpOnly, and Secure on HTTPS;
697
+ * no Domain/path/security opt-outs. One pending flow per cookie name: a fresh
698
+ * initiation replaces it. Use distinct names for multiple vault mounts.
699
+ */
700
+ interface OidcVaultTransactionCookieOptions {
701
+ /**
702
+ * HTTP cookie token, distinct from the session cookie. HTTPS defaults to
703
+ * __Host-oidc_vault_transaction; loopback HTTP to oidc_vault_transaction.
704
+ * __Host-/__Secure- prefixes require HTTPS.
705
+ */
706
+ name?: string;
707
+ /** Default lax permits the provider's top-level GET callback. Explicit none requires HTTPS for cross-site SPAs. */
708
+ sameSite?: 'lax' | 'none';
709
+ }
403
710
  interface OidcVaultCookieOptions {
404
711
  /**
405
712
  * Session cookie name. Must be a valid HTTP cookie name (printable ASCII
@@ -440,8 +747,11 @@ interface OidcVaultCookieOptions {
440
747
  httpOnly?: boolean;
441
748
  }
442
749
  interface OidcVaultOptions {
750
+ /** Public router mount; default /auth/oidc. DPoP vault proxies must preserve this externally visible path. */
443
751
  basePath?: string;
752
+ /** Pinned public callback/proof origin. DPoP requires a static HTTPS origin, with loopback HTTP allowed for development. */
444
753
  backendOrigin: string;
754
+ /** Vault persistence and, when DPoP is enabled, atomic replay admission. All six stronger capabilities are required for either opt-in feature. */
445
755
  storeProvider: OidcVaultStoreProvider;
446
756
  config?: OidcVaultConfig;
447
757
  /**
@@ -455,6 +765,31 @@ interface OidcVaultOptions {
455
765
  hooks?: OidcVaultHooks;
456
766
  /** Optional local issuer; when omitted, exchange/refresh return no local token fields. */
457
767
  tokenIssuer?: OidcVaultTokenIssuer;
768
+ /**
769
+ * Opt-in DPoP policy; absent preserves unbound bearer behavior. Present with
770
+ * no mode means `optional`. Requires all `OidcVaultDeviceBindingStoreProvider`
771
+ * capabilities and a static HTTPS `backendOrigin` (loopback HTTP development
772
+ * is allowed). Bound exchange/refresh/logout require a fresh original-key
773
+ * DPoP header before code consumption, upstream refresh, hooks or revocation;
774
+ * vault POSTs need no Authorization access token/ath. A supplied optional
775
+ * unbound proof validates/reserves but never enrolls or rebinds. Construction
776
+ * snapshots/freezes plain options and algorithms and copies nonce bytes.
777
+ */
778
+ deviceBinding?: OidcVaultDeviceBindingOptions;
779
+ /**
780
+ * Separate opt-in recognition policy; omission means no signal capture/check.
781
+ * Enables JSON POST login and its temporary HttpOnly cookie in both session
782
+ * transports, even without DPoP; requires all guarded-store capabilities.
783
+ * POST login alone enrolls a supplied signal in reserved metadata. Enrolled
784
+ * exchange/refresh compare before proof admission/code consume/upstream use:
785
+ * missing/mismatch returns 403 OIDC_VAULT_FINGERPRINT_REAUTH_REQUIRED without
786
+ * mutation. Legacy/GET/absent-signal sessions remain unenrolled. Refresh never
787
+ * enrolls/rotates recognition; changes require fresh POST login. Logout,
788
+ * rotation aliases, signed backchannel logout and API recognition policy are
789
+ * unaffected. Disclose collection and transaction/session retention, including
790
+ * store cleanup/backups; hashing is not anonymization or theft prevention.
791
+ */
792
+ fingerprintRecognition?: OidcVaultFingerprintRecognitionOptions;
458
793
  /**
459
794
  * Default browser return target after backend callback completion. Required
460
795
  * if login accepts a custom `returnTo`. Remains optional at middleware
@@ -473,6 +808,7 @@ interface OidcVaultOptions {
473
808
  * session). Discovery errors also reach `onError`.
474
809
  */
475
810
  postLogoutRedirectUri?: string;
811
+ /** Default enabled when discovery/manual config has a UserInfo endpoint and the response supplies an access token; false disables it. */
476
812
  fetchUserInfo?: boolean;
477
813
  /**
478
814
  * Authorization transaction lifetime in milliseconds (default: 10 minutes).
@@ -499,8 +835,27 @@ interface OidcVaultOptions {
499
835
  * store-owned lifetime behavior; no default session expiry is assigned.
500
836
  */
501
837
  sessionTtlMs?: number;
838
+ /** Default body: JSON sessionId. Cookie mode omits that handle from JSON; POST login/exchange need the temporary cookie in both modes. */
502
839
  sessionTransport?: OidcVaultSessionTransport;
503
840
  cookie?: OidcVaultCookieOptions;
841
+ /**
842
+ * Detached/frozen transaction-cookie settings, independent of session
843
+ * transport. POST login stores only SHA-256(cookie secret) and the verified
844
+ * initiating jkt when bound; callback authenticates and atomically spends the
845
+ * stored match. Guarded exchange needs this cookie in both session transports
846
+ * plus the original-key proof when bound. Success/authenticated terminal
847
+ * issuance failure clears it; mismatches and nonce challenges do not spend or
848
+ * clear. Cookie lifetime rounds down to the transaction/code deadline.
849
+ */
850
+ transactionCookie?: OidcVaultTransactionCookieOptions;
851
+ /**
852
+ * Allowed browser source origins: POST login uses this policy in both
853
+ * transports; guarded exchange uses the same policy (JSON or form), and
854
+ * cookie refresh/logout retain their source checks. Missing/null/untrusted
855
+ * sources fail closed; POST login/guarded exchange also reject raw source
856
+ * ambiguity. backendOrigin is included internally; a valid Referer is the
857
+ * fallback only when Origin is absent.
858
+ */
504
859
  trustedOrigins?: string[];
505
860
  requestBodyLimit?: string | number;
506
861
  /**
@@ -571,30 +926,66 @@ declare const DEFAULT_OIDC_VAULT_REQUEST_BODY_LIMIT = "16kb";
571
926
  declare const OIDC_VAULT_URL_ENCODED_PARAMETER_LIMIT = 16;
572
927
  declare const OIDC_VAULT_ROUTE_PATHS: Record<OidcVaultRouteName, string>;
573
928
 
929
+ /**
930
+ * API authentication from package-root named imports. With deviceBinding
931
+ * enabled, requires validateWithRequest at construction for BOTH schemes and
932
+ * verifies a single raw DPoP proof, pinned method/URL, original confirmation,
933
+ * API ath, nonce and shared replay BEFORE attaching req.auth or invoking hooks.
934
+ * Bound tokens require Authorization: DPoP; unbound DPoP presentation is invalid.
935
+ * Omitted binding retains exactly validate(token) for legacy Bearer adapters,
936
+ * but refuses any known bound credential. Construction snapshots configuration,
937
+ * callbacks/validator methods, URLs, algorithms and secret bytes; the replay
938
+ * store remains the shared atomic service. Responses carry no-store and fixed
939
+ * errors; onError privately observes originals and cannot override failures.
940
+ */
574
941
  declare function createOidcVaultAccessTokenMiddleware(options: OidcVaultAccessTokenMiddlewareOptions): RequestHandler;
575
942
 
576
- declare function createOidcVaultJwtAccessTokenValidator(options: OidcVaultJwtAccessTokenValidatorOptions): {
577
- validate(token: string): Promise<OidcVaultAccessTokenValidationResult>;
578
- };
943
+ /**
944
+ * Verify local JWTs with both legacy validate(token) and validateWithRequest.
945
+ * Raw verified cnf is captured before mapClaims; mapping cannot forge or strip
946
+ * the sender constraint. The request-aware result always has confirmation
947
+ * (null only for genuinely unbound JWTs). Legacy unbound results omit it;
948
+ * bound results report it so binding-disabled vault middleware refuses downgrade.
949
+ * Proof/target/ath/nonce/replay enforcement belongs to the API middleware.
950
+ * Construction captures options and copies secret/JWK/allowlist containers.
951
+ */
952
+ declare function createOidcVaultJwtAccessTokenValidator(options: OidcVaultJwtAccessTokenValidatorOptions): OidcVaultRequestAwareAccessTokenValidator;
579
953
 
580
954
  /**
581
955
  * Normalize the mounted base path for the OIDC router.
582
956
  */
583
957
  declare function normalizeOidcVaultBasePath(value?: string): string;
584
958
  /**
585
- * Create the core OIDC vault middleware.
959
+ * Create the OIDC lifecycle router using a named package-root import.
960
+ * The default mount is /auth/oidc and default transport is body. Configure
961
+ * issuer/clientId (or complete manual endpoints), a pinned backendOrigin,
962
+ * frontendRedirectUri for callback completion, and a storeProvider.
963
+ *
964
+ * With deviceBinding enabled, JSON POST login selects a verified persistent
965
+ * browser key, callback authenticates the temporary HttpOnly cookie, and
966
+ * exchange/refresh/logout enforce the original key before credential work.
967
+ * A local tokenIssuer must emit exact DPoP and matching cnf.jkt from its verified
968
+ * input. Protect every accepting API separately with
969
+ * createOidcVaultAccessTokenMiddleware and a request-aware validator/replay store.
970
+ * Vault refresh/logout need no access token or ath and work after JWT expiry.
971
+ * All vault responses carry no-store; logout does not revoke stateless JWTs.
586
972
  *
587
973
  * Construction takes an internal resolved snapshot of `options` without
588
974
  * mutating the caller object: normalized values (such as
589
975
  * `frontendRedirectUri`) are stored on the snapshot, plain-data containers
590
- * (`cookie`, `trustedOrigins`, `config`) are shallow-copied, and service
976
+ * (`cookie`, `trustedOrigins`, `config`) are shallow-copied, `transactionCookie`
977
+ * is resolved into a detached/frozen security configuration, and service
591
978
  * references (`storeProvider`, `hooks`, `tokenIssuer`, `now`) are retained
592
979
  * by reference, never deep-cloned. Mutating or replacing the caller options
593
980
  * after this call has no effect on the created router. Post-commit hooks
594
981
  * (`onSessionCreated`, `onSessionRefreshed`, `onLogout`) are notifications
595
982
  * whose failures are reported to `onError` without undoing committed state;
596
983
  * other hooks run pre-commit and can veto the operation by throwing.
984
+ * Opt-in `deviceBinding` policy/algorithm containers are frozen snapshots;
985
+ * an enabled nonce secret is copied into private owned storage. Separate opt-in
986
+ * `fingerprintRecognition` settings are detached/frozen; recognition enrolls
987
+ * only at POST login and checks exchange/refresh before credential mutation.
597
988
  */
598
989
  declare function createOidcVaultMiddleware(options: OidcVaultOptions): Router;
599
990
 
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 };
991
+ export { type AuthorizationTransaction, type AuthorizationTransactionInput, type ConsumeAuthorizationTransactionIfMatchesInput, type ConsumeBackchannelLogoutTokenJtiInput, type ConsumeExchangeCodeIfMatchesInput, 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 OidcVaultAccessTokenConfirmation, type OidcVaultAccessTokenMiddlewareErrorContext, type OidcVaultAccessTokenMiddlewareOptions, type OidcVaultAccessTokenRequestInput, type OidcVaultAccessTokenValidationResult, type OidcVaultAccessTokenValidator, type OidcVaultApiDeviceBindingOptions, type OidcVaultAuthContext, type OidcVaultAuthenticatedRequest, type OidcVaultBackchannelLogoutResult, type OidcVaultConfig, type OidcVaultConfigMode, type OidcVaultCookieDeploymentMode, type OidcVaultCookieOptions, type OidcVaultCookieSameSite, type OidcVaultDeviceBindingMode, type OidcVaultDeviceBindingOptions, type OidcVaultDeviceBindingStoreProvider, type OidcVaultDpopAlgorithm, type OidcVaultDpopBinding, type OidcVaultDpopNonceOptions, type OidcVaultDpopProofOptions, OidcVaultDpopReplayCapacityError, type OidcVaultDpopReplayStore, type OidcVaultEnv, type OidcVaultErrorContext, type OidcVaultExchangeResult, type OidcVaultFingerprintRecognitionOptions, type OidcVaultHookContext, type OidcVaultHooks, type OidcVaultJwtAccessTokenValidatorOptions, type OidcVaultLoginInitiationInput, type OidcVaultLoginInitiationResult, type OidcVaultLogoutResult, type OidcVaultOptions, type OidcVaultProviderMetadata, type OidcVaultRecordBindingMatch, type OidcVaultRequestAwareAccessTokenValidationResult, type OidcVaultRequestAwareAccessTokenValidator, type OidcVaultResolvedConfig, type OidcVaultRouteName, type OidcVaultSession, type OidcVaultSessionInput, type OidcVaultSessionRevocationContext, type OidcVaultSessionTransport, OidcVaultStoreConflictError, type OidcVaultStoreProvider, type OidcVaultTokenIssueResult, type OidcVaultTokenIssuer, type OidcVaultTransactionCookieOptions, type OidcVaultUserProfile, type OidcVaultVerifiedDpopBinding, type ReserveDpopProofInput, type RotateSessionInput, createOidcVaultAccessTokenMiddleware, createOidcVaultJwtAccessTokenValidator, createOidcVaultMiddleware, normalizeOidcVaultBasePath, resolveOidcVaultConfig, resolveOidcVaultConfigFromEnv };