@web-ts-toolkit/express-oidc-vault 0.51.0 → 0.52.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/index.d.mts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { Request, Response, RequestHandler, Router } from 'express';
2
2
  import { KeyObject } from 'node:crypto';
3
3
  import { JWK } from 'jose';
4
+ import { OidcVaultUserProfile, OidcVaultTokenIssueResult, OidcVaultSessionTransport } from './wire.mjs';
5
+ export { OidcVaultExchangeResult, OidcVaultLoginInitiationInput, OidcVaultLoginInitiationResult, OidcVaultLogoutResult } from './wire.mjs';
4
6
 
5
7
  type OidcVaultRouteName = 'login' | 'callback' | 'exchange' | 'refresh' | 'logout' | 'backchannel-logout';
6
8
  /** Enabling the option defaults to `optional`; omitting it keeps bearer behavior. */
@@ -114,13 +116,6 @@ interface OidcVaultApiDeviceBindingOptions extends OidcVaultDeviceBindingOptions
114
116
  /** Epoch-millisecond clock for proof age/nonce/replay; default Date.now. Shared instances need synchronized clocks. */
115
117
  now?: () => number;
116
118
  }
117
- interface OidcVaultUserProfile {
118
- sub: string;
119
- email?: string;
120
- name?: string;
121
- preferredUsername?: string;
122
- [key: string]: unknown;
123
- }
124
119
  /**
125
120
  * Stored session identity. Exchange, refresh, and logout compare each defined
126
121
  * field verbatim against resolved middleware config before use. Opt-in/guarded
@@ -515,19 +510,6 @@ interface IssueTokenInput {
515
510
  */
516
511
  deviceBinding?: Readonly<OidcVaultVerifiedDpopBinding>;
517
512
  }
518
- /**
519
- * Local application credentials returned by `OidcVaultTokenIssuer.issue`.
520
- * Runtime validation copies only these fields into a fresh result; additional
521
- * properties are ignored and cannot override the response's session ID/user.
522
- */
523
- interface OidcVaultTokenIssueResult {
524
- /** Nonempty opaque token for unbound issuance; bound issuance requires a compact signed JWT with matching `cnf.jkt`. */
525
- accessToken: string;
526
- /** Token lifetime in seconds: a finite, nonnegative safe integer (zero is valid). */
527
- expiresIn: number;
528
- /** Exact `DPoP` is required when bound. Unbound permits only `Bearer` or omission; omitted/undefined stays absent in JSON. */
529
- tokenType?: 'Bearer' | 'DPoP';
530
- }
531
513
  /**
532
514
  * Trusted application token issuer for exchange and refresh. Return a non-null,
533
515
  * non-array object satisfying `OidcVaultTokenIssueResult`; only its declared
@@ -554,7 +536,7 @@ interface OidcVaultAccessTokenValidationResult {
554
536
  /** Verified sender constraint. Legacy adapters may omit it only for genuinely unbound credentials. */
555
537
  confirmation?: OidcVaultAccessTokenConfirmation | null;
556
538
  }
557
- /** Canonical RFC 7638 SHA-256 thumbprint derived from verified token/introspection data, never from a proof alone. */
539
+ /** Exact one-field confirmation: canonical RFC 7638 SHA-256 thumbprint from verified token/introspection data, never from a proof alone. */
558
540
  interface OidcVaultAccessTokenConfirmation {
559
541
  jkt: string;
560
542
  }
@@ -628,13 +610,18 @@ interface OidcVaultAccessTokenMiddlewareOptions {
628
610
  interface OidcVaultAuthenticatedRequest extends Request {
629
611
  auth?: OidcVaultAuthContext;
630
612
  }
631
- /** Local JWT verification options, independent of the asymmetric DPoP proof policy; captured at construction. */
613
+ /**
614
+ * Local JWT verification options, independent of the asymmetric DPoP proof
615
+ * policy; captured at construction. JWTs with cnf require the supported exact
616
+ * jkt profile and a nonnegative safe-integer exp with safe milliseconds in both
617
+ * validator methods. Unbound JWTs retain JOSE's optional-exp behavior.
618
+ */
632
619
  interface OidcVaultJwtAccessTokenValidatorOptions {
633
620
  key: CryptoKey | KeyObject | JWK | Uint8Array;
634
621
  issuer?: string;
635
622
  audience?: string | string[];
636
623
  algorithms?: string[];
637
- /** Verified cnf is snapshotted before this mapper; mapper-supplied confirmation/deviceBinding is ignored. */
624
+ /** JOSE verification and bound-JWT profile/expiry checks precede this mapper. Original cnf is snapshotted; mapper-supplied confirmation/deviceBinding is ignored. */
638
625
  mapClaims?(claims: Record<string, unknown>): OidcVaultAccessTokenValidationResult;
639
626
  }
640
627
  declare module 'express-serve-static-core' {
@@ -666,50 +653,10 @@ interface OidcVaultConfig {
666
653
  clientSecret?: string;
667
654
  scopes?: string;
668
655
  }
669
- interface OidcVaultLogoutResult {
670
- /**
671
- * Successful logout commits revocation before upstream work and clears the
672
- * session cookie under cookie transport. Built-in live handles and unexpired
673
- * aliases authenticate the surviving lineage's provider/original binding;
674
- * wrong identity, missing/wrong/stale/replayed proof, or disabled acceptance
675
- * of a bound lineage fails without deleting or clearing. No currently live
676
- * target is idempotent success without deletion or proof reservation. Aliases
677
- * grant revocation only, not refresh authentication or upstream redirects.
678
- * Old custom bearer stores without revocation context retain legacy alias
679
- * deletion behavior. Stateless application access tokens are not invalidated.
680
- * Local-only logout (`redirect` unset or `false`) never contacts the provider.
681
- * Redirected logout (`redirect: true`)
682
- * treats the upstream end-session redirect as best-effort: when provider
683
- * discovery fails or no `endSessionEndpoint` is available, the route still
684
- * returns this local success. Discovery errors reach `onError` without
685
- * undoing revocation or skipping the live session's `onLogout` notification.
686
- */
687
- loggedOut: true;
688
- }
689
656
  interface OidcVaultBackchannelLogoutResult {
690
657
  loggedOut: true;
691
658
  revokedSessions: number;
692
659
  }
693
- interface OidcVaultExchangeResult extends Partial<OidcVaultTokenIssueResult> {
694
- /** Authoritative vault handle in body transport; omitted from cookie-transport JSON. */
695
- sessionId?: string;
696
- /** Session profile; extra token-issuer result properties cannot override it. */
697
- user?: OidcVaultUserProfile;
698
- }
699
- /** JSON body for opt-in `POST <basePath>/login`; proof/key and recognition signals belong in their configured headers, not the body. */
700
- interface OidcVaultLoginInitiationInput {
701
- /** Optional destination on the configured frontend origin. Query-string returnTo is ignored by POST login. */
702
- returnTo?: string;
703
- }
704
- /**
705
- * Exact successful POST-login JSON. Navigate to this URL after storing a proof
706
- * key when DPoP is enabled. Use credentials: 'include' even with body session
707
- * transport: initiation sets a temporary HttpOnly transaction cookie.
708
- */
709
- interface OidcVaultLoginInitiationResult {
710
- authorizationUrl: string;
711
- }
712
- type OidcVaultSessionTransport = 'body' | 'cookie';
713
660
  type OidcVaultCookieDeploymentMode = 'same-origin' | 'same-site' | 'cross-site';
714
661
  type OidcVaultCookieSameSite = 'lax' | 'strict' | 'none';
715
662
  /**
@@ -971,6 +918,10 @@ declare function createOidcVaultAccessTokenMiddleware(options: OidcVaultAccessTo
971
918
  * the sender constraint. The request-aware result always has confirmation
972
919
  * (null only for genuinely unbound JWTs). Legacy unbound results omit it;
973
920
  * bound results report it so binding-disabled vault middleware refuses downgrade.
921
+ * Bound JWTs additionally require canonical compact encoding and a nonnegative
922
+ * safe-integer exp with safe milliseconds, checked before mapClaims in both
923
+ * methods. JOSE verifies signature/expiry and configured issuer/audience first. Unbound
924
+ * JWTs retain JOSE's generic optional-exp contract.
974
925
  * Proof/target/ath/nonce/replay enforcement belongs to the API middleware.
975
926
  * Construction captures options and copies secret/JWK/allowlist containers.
976
927
  */
@@ -1017,4 +968,4 @@ declare function normalizeOidcVaultBasePath(value?: string): string;
1017
968
  */
1018
969
  declare function createOidcVaultMiddleware(options: OidcVaultOptions): Router;
1019
970
 
1020
- 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 };
971
+ 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 OidcVaultFingerprintRecognitionOptions, type OidcVaultHookContext, type OidcVaultHooks, type OidcVaultJwtAccessTokenValidatorOptions, type OidcVaultOptions, type OidcVaultProviderMetadata, type OidcVaultRecordBindingMatch, type OidcVaultRequestAwareAccessTokenValidationResult, type OidcVaultRequestAwareAccessTokenValidator, type OidcVaultResolvedConfig, type OidcVaultRouteName, type OidcVaultSession, type OidcVaultSessionInput, type OidcVaultSessionRevocationContext, OidcVaultSessionTransport, OidcVaultStoreConflictError, type OidcVaultStoreProvider, OidcVaultTokenIssueResult, type OidcVaultTokenIssuer, type OidcVaultTransactionCookieOptions, OidcVaultUserProfile, type OidcVaultVerifiedDpopBinding, type ReserveDpopProofInput, type RotateSessionInput, createOidcVaultAccessTokenMiddleware, createOidcVaultJwtAccessTokenValidator, createOidcVaultMiddleware, normalizeOidcVaultBasePath, resolveOidcVaultConfig, resolveOidcVaultConfigFromEnv };
package/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { Request, Response, RequestHandler, Router } from 'express';
2
2
  import { KeyObject } from 'node:crypto';
3
3
  import { JWK } from 'jose';
4
+ import { OidcVaultUserProfile, OidcVaultTokenIssueResult, OidcVaultSessionTransport } from './wire.js';
5
+ export { OidcVaultExchangeResult, OidcVaultLoginInitiationInput, OidcVaultLoginInitiationResult, OidcVaultLogoutResult } from './wire.js';
4
6
 
5
7
  type OidcVaultRouteName = 'login' | 'callback' | 'exchange' | 'refresh' | 'logout' | 'backchannel-logout';
6
8
  /** Enabling the option defaults to `optional`; omitting it keeps bearer behavior. */
@@ -114,13 +116,6 @@ interface OidcVaultApiDeviceBindingOptions extends OidcVaultDeviceBindingOptions
114
116
  /** Epoch-millisecond clock for proof age/nonce/replay; default Date.now. Shared instances need synchronized clocks. */
115
117
  now?: () => number;
116
118
  }
117
- interface OidcVaultUserProfile {
118
- sub: string;
119
- email?: string;
120
- name?: string;
121
- preferredUsername?: string;
122
- [key: string]: unknown;
123
- }
124
119
  /**
125
120
  * Stored session identity. Exchange, refresh, and logout compare each defined
126
121
  * field verbatim against resolved middleware config before use. Opt-in/guarded
@@ -515,19 +510,6 @@ interface IssueTokenInput {
515
510
  */
516
511
  deviceBinding?: Readonly<OidcVaultVerifiedDpopBinding>;
517
512
  }
518
- /**
519
- * Local application credentials returned by `OidcVaultTokenIssuer.issue`.
520
- * Runtime validation copies only these fields into a fresh result; additional
521
- * properties are ignored and cannot override the response's session ID/user.
522
- */
523
- interface OidcVaultTokenIssueResult {
524
- /** Nonempty opaque token for unbound issuance; bound issuance requires a compact signed JWT with matching `cnf.jkt`. */
525
- accessToken: string;
526
- /** Token lifetime in seconds: a finite, nonnegative safe integer (zero is valid). */
527
- expiresIn: number;
528
- /** Exact `DPoP` is required when bound. Unbound permits only `Bearer` or omission; omitted/undefined stays absent in JSON. */
529
- tokenType?: 'Bearer' | 'DPoP';
530
- }
531
513
  /**
532
514
  * Trusted application token issuer for exchange and refresh. Return a non-null,
533
515
  * non-array object satisfying `OidcVaultTokenIssueResult`; only its declared
@@ -554,7 +536,7 @@ interface OidcVaultAccessTokenValidationResult {
554
536
  /** Verified sender constraint. Legacy adapters may omit it only for genuinely unbound credentials. */
555
537
  confirmation?: OidcVaultAccessTokenConfirmation | null;
556
538
  }
557
- /** Canonical RFC 7638 SHA-256 thumbprint derived from verified token/introspection data, never from a proof alone. */
539
+ /** Exact one-field confirmation: canonical RFC 7638 SHA-256 thumbprint from verified token/introspection data, never from a proof alone. */
558
540
  interface OidcVaultAccessTokenConfirmation {
559
541
  jkt: string;
560
542
  }
@@ -628,13 +610,18 @@ interface OidcVaultAccessTokenMiddlewareOptions {
628
610
  interface OidcVaultAuthenticatedRequest extends Request {
629
611
  auth?: OidcVaultAuthContext;
630
612
  }
631
- /** Local JWT verification options, independent of the asymmetric DPoP proof policy; captured at construction. */
613
+ /**
614
+ * Local JWT verification options, independent of the asymmetric DPoP proof
615
+ * policy; captured at construction. JWTs with cnf require the supported exact
616
+ * jkt profile and a nonnegative safe-integer exp with safe milliseconds in both
617
+ * validator methods. Unbound JWTs retain JOSE's optional-exp behavior.
618
+ */
632
619
  interface OidcVaultJwtAccessTokenValidatorOptions {
633
620
  key: CryptoKey | KeyObject | JWK | Uint8Array;
634
621
  issuer?: string;
635
622
  audience?: string | string[];
636
623
  algorithms?: string[];
637
- /** Verified cnf is snapshotted before this mapper; mapper-supplied confirmation/deviceBinding is ignored. */
624
+ /** JOSE verification and bound-JWT profile/expiry checks precede this mapper. Original cnf is snapshotted; mapper-supplied confirmation/deviceBinding is ignored. */
638
625
  mapClaims?(claims: Record<string, unknown>): OidcVaultAccessTokenValidationResult;
639
626
  }
640
627
  declare module 'express-serve-static-core' {
@@ -666,50 +653,10 @@ interface OidcVaultConfig {
666
653
  clientSecret?: string;
667
654
  scopes?: string;
668
655
  }
669
- interface OidcVaultLogoutResult {
670
- /**
671
- * Successful logout commits revocation before upstream work and clears the
672
- * session cookie under cookie transport. Built-in live handles and unexpired
673
- * aliases authenticate the surviving lineage's provider/original binding;
674
- * wrong identity, missing/wrong/stale/replayed proof, or disabled acceptance
675
- * of a bound lineage fails without deleting or clearing. No currently live
676
- * target is idempotent success without deletion or proof reservation. Aliases
677
- * grant revocation only, not refresh authentication or upstream redirects.
678
- * Old custom bearer stores without revocation context retain legacy alias
679
- * deletion behavior. Stateless application access tokens are not invalidated.
680
- * Local-only logout (`redirect` unset or `false`) never contacts the provider.
681
- * Redirected logout (`redirect: true`)
682
- * treats the upstream end-session redirect as best-effort: when provider
683
- * discovery fails or no `endSessionEndpoint` is available, the route still
684
- * returns this local success. Discovery errors reach `onError` without
685
- * undoing revocation or skipping the live session's `onLogout` notification.
686
- */
687
- loggedOut: true;
688
- }
689
656
  interface OidcVaultBackchannelLogoutResult {
690
657
  loggedOut: true;
691
658
  revokedSessions: number;
692
659
  }
693
- interface OidcVaultExchangeResult extends Partial<OidcVaultTokenIssueResult> {
694
- /** Authoritative vault handle in body transport; omitted from cookie-transport JSON. */
695
- sessionId?: string;
696
- /** Session profile; extra token-issuer result properties cannot override it. */
697
- user?: OidcVaultUserProfile;
698
- }
699
- /** JSON body for opt-in `POST <basePath>/login`; proof/key and recognition signals belong in their configured headers, not the body. */
700
- interface OidcVaultLoginInitiationInput {
701
- /** Optional destination on the configured frontend origin. Query-string returnTo is ignored by POST login. */
702
- returnTo?: string;
703
- }
704
- /**
705
- * Exact successful POST-login JSON. Navigate to this URL after storing a proof
706
- * key when DPoP is enabled. Use credentials: 'include' even with body session
707
- * transport: initiation sets a temporary HttpOnly transaction cookie.
708
- */
709
- interface OidcVaultLoginInitiationResult {
710
- authorizationUrl: string;
711
- }
712
- type OidcVaultSessionTransport = 'body' | 'cookie';
713
660
  type OidcVaultCookieDeploymentMode = 'same-origin' | 'same-site' | 'cross-site';
714
661
  type OidcVaultCookieSameSite = 'lax' | 'strict' | 'none';
715
662
  /**
@@ -971,6 +918,10 @@ declare function createOidcVaultAccessTokenMiddleware(options: OidcVaultAccessTo
971
918
  * the sender constraint. The request-aware result always has confirmation
972
919
  * (null only for genuinely unbound JWTs). Legacy unbound results omit it;
973
920
  * bound results report it so binding-disabled vault middleware refuses downgrade.
921
+ * Bound JWTs additionally require canonical compact encoding and a nonnegative
922
+ * safe-integer exp with safe milliseconds, checked before mapClaims in both
923
+ * methods. JOSE verifies signature/expiry and configured issuer/audience first. Unbound
924
+ * JWTs retain JOSE's generic optional-exp contract.
974
925
  * Proof/target/ath/nonce/replay enforcement belongs to the API middleware.
975
926
  * Construction captures options and copies secret/JWK/allowlist containers.
976
927
  */
@@ -1017,4 +968,4 @@ declare function normalizeOidcVaultBasePath(value?: string): string;
1017
968
  */
1018
969
  declare function createOidcVaultMiddleware(options: OidcVaultOptions): Router;
1019
970
 
1020
- 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 };
971
+ 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 OidcVaultFingerprintRecognitionOptions, type OidcVaultHookContext, type OidcVaultHooks, type OidcVaultJwtAccessTokenValidatorOptions, type OidcVaultOptions, type OidcVaultProviderMetadata, type OidcVaultRecordBindingMatch, type OidcVaultRequestAwareAccessTokenValidationResult, type OidcVaultRequestAwareAccessTokenValidator, type OidcVaultResolvedConfig, type OidcVaultRouteName, type OidcVaultSession, type OidcVaultSessionInput, type OidcVaultSessionRevocationContext, OidcVaultSessionTransport, OidcVaultStoreConflictError, type OidcVaultStoreProvider, OidcVaultTokenIssueResult, type OidcVaultTokenIssuer, type OidcVaultTransactionCookieOptions, OidcVaultUserProfile, type OidcVaultVerifiedDpopBinding, type ReserveDpopProofInput, type RotateSessionInput, createOidcVaultAccessTokenMiddleware, createOidcVaultJwtAccessTokenValidator, createOidcVaultMiddleware, normalizeOidcVaultBasePath, resolveOidcVaultConfig, resolveOidcVaultConfigFromEnv };
package/index.js CHANGED
@@ -1833,6 +1833,35 @@ async function fetchUserInfo(metadata, accessToken, options = {}) {
1833
1833
  // src/token-issuance.ts
1834
1834
  var import_jose3 = require("jose");
1835
1835
 
1836
+ // src/access-token-confirmation.ts
1837
+ var invalidAccessToken = (diagnostic) => new OidcVaultHttpError(401, "OIDC_VAULT_INVALID_ACCESS_TOKEN", diagnostic, "Access token validation failed.");
1838
+ var snapshotJkt = (value, invalid = invalidAccessToken) => {
1839
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1840
+ throw invalid("Access token confirmation must be a plain jkt object.");
1841
+ }
1842
+ const prototype = Object.getPrototypeOf(value);
1843
+ const keys = Reflect.ownKeys(value);
1844
+ if (prototype !== Object.prototype && prototype !== null || keys.length !== 1 || keys[0] !== "jkt") {
1845
+ throw invalid("Access token confirmation contains unsupported fields.");
1846
+ }
1847
+ const { jkt } = value;
1848
+ if (!isCanonicalDpopJkt(jkt)) throw invalid("Access token confirmation is not a canonical SHA-256 thumbprint.");
1849
+ return Object.freeze({ jkt });
1850
+ };
1851
+ var isCompactSignedJwt = (token) => {
1852
+ const parts = token.split(".");
1853
+ return parts.length === 3 && parts.every(
1854
+ (part) => /^[A-Za-z0-9_-]+$/.test(part) ? Buffer.from(part, "base64url").toString("base64url") === part : false
1855
+ );
1856
+ };
1857
+ var readJwtExpirationMs = (exp) => {
1858
+ if (typeof exp !== "number" || !Number.isSafeInteger(exp) || exp < 0) return void 0;
1859
+ const milliseconds = exp * 1e3;
1860
+ return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;
1861
+ };
1862
+ var snapshotVerifiedJwtConfirmation = (claims) => Object.hasOwn(claims, "cnf") ? snapshotJkt(claims.cnf) : null;
1863
+ var snapshotAccessTokenConfirmation = (value) => value === null ? null : snapshotJkt(value);
1864
+
1836
1865
  // src/vault-session.ts
1837
1866
  var invalidVaultSession = () => new OidcVaultHttpError(401, "OIDC_VAULT_INVALID_SESSION", "Session is missing or expired.");
1838
1867
  var invalidExchangeCode = () => new OidcVaultHttpError(400, "OIDC_VAULT_INVALID_EXCHANGE_CODE", "Exchange code is invalid or expired.");
@@ -1977,13 +2006,7 @@ var createExchangeResponse = (options, session, issuedToken) => ({
1977
2006
  expiresIn: issuedToken.expiresIn,
1978
2007
  tokenType: issuedToken.tokenType
1979
2008
  });
1980
- var isCompactSignedJwt = (token) => {
1981
- const parts = token.split(".");
1982
- return parts.length === 3 && parts.every(
1983
- (part) => /^[A-Za-z0-9_-]+$/.test(part) ? Buffer.from(part, "base64url").toString("base64url") === part : false
1984
- );
1985
- };
1986
- var assertIssuedTokenConfirmation = (accessToken, jkt) => {
2009
+ var assertIssuedBoundJwt = (accessToken, jkt) => {
1987
2010
  if (!isCompactSignedJwt(accessToken)) {
1988
2011
  throw new TypeError("tokenIssuer.issue accessToken must be a compact signed JWT for bound issuance.");
1989
2012
  }
@@ -1998,10 +2021,16 @@ var assertIssuedTokenConfirmation = (accessToken, jkt) => {
1998
2021
  if (typeof header.alg !== "string" || header.alg.length === 0 || header.alg === "none" || header.b64 === false) {
1999
2022
  throw new TypeError("tokenIssuer.issue accessToken must use a signed JWT algorithm for bound issuance.");
2000
2023
  }
2001
- const cnf = claims.cnf;
2002
- if (typeof cnf !== "object" || cnf === null || Array.isArray(cnf) || cnf.jkt !== jkt) {
2024
+ const confirmation = snapshotJkt(
2025
+ claims.cnf,
2026
+ (diagnostic) => new TypeError(`tokenIssuer.issue accessToken cnf.jkt is invalid. ${diagnostic}`)
2027
+ );
2028
+ if (confirmation.jkt !== jkt) {
2003
2029
  throw new TypeError("tokenIssuer.issue accessToken cnf.jkt must match the verified device binding.");
2004
2030
  }
2031
+ if (readJwtExpirationMs(claims.exp) === void 0) {
2032
+ throw new TypeError("tokenIssuer.issue accessToken exp must be a nonnegative safe integer with safe milliseconds.");
2033
+ }
2005
2034
  };
2006
2035
  var withIssuedToken = async (req, res, options, session, verifiedBinding) => {
2007
2036
  const binding = resolveVerifiedDeviceBinding(options.deviceBinding, session.deviceBinding, verifiedBinding);
@@ -2034,7 +2063,10 @@ var withIssuedToken = async (req, res, options, session, verifiedBinding) => {
2034
2063
  }
2035
2064
  } else {
2036
2065
  if (tokenType !== "DPoP") throw new TypeError("tokenIssuer.issue tokenType must be DPoP for bound issuance.");
2037
- assertIssuedTokenConfirmation(accessToken, binding.jkt);
2066
+ if (!Number.isSafeInteger(expiresIn * 1e3)) {
2067
+ throw new TypeError("tokenIssuer.issue expiresIn must have safe milliseconds for bound issuance.");
2068
+ }
2069
+ assertIssuedBoundJwt(accessToken, binding.jkt);
2038
2070
  }
2039
2071
  return { accessToken, expiresIn, ...tokenType === void 0 ? {} : { tokenType } };
2040
2072
  } catch (error) {
@@ -2046,27 +2078,6 @@ var withIssuedToken = async (req, res, options, session, verifiedBinding) => {
2046
2078
 
2047
2079
  // src/token-validation.ts
2048
2080
  var import_jose4 = require("jose");
2049
-
2050
- // src/access-token-confirmation.ts
2051
- var invalidAccessToken = (diagnostic) => new OidcVaultHttpError(401, "OIDC_VAULT_INVALID_ACCESS_TOKEN", diagnostic, "Access token validation failed.");
2052
- var snapshotJkt = (value) => {
2053
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
2054
- throw invalidAccessToken("Access token confirmation must be a plain jkt object.");
2055
- }
2056
- const prototype = Object.getPrototypeOf(value);
2057
- const keys = Reflect.ownKeys(value);
2058
- if (prototype !== Object.prototype && prototype !== null || keys.length !== 1 || keys[0] !== "jkt") {
2059
- throw invalidAccessToken("Access token confirmation contains unsupported fields.");
2060
- }
2061
- const { jkt } = value;
2062
- if (!isCanonicalDpopJkt(jkt))
2063
- throw invalidAccessToken("Access token confirmation is not a canonical SHA-256 thumbprint.");
2064
- return Object.freeze({ jkt });
2065
- };
2066
- var snapshotVerifiedJwtConfirmation = (claims) => Object.hasOwn(claims, "cnf") ? snapshotJkt(claims.cnf) : null;
2067
- var snapshotAccessTokenConfirmation = (value) => value === null ? null : snapshotJkt(value);
2068
-
2069
- // src/token-validation.ts
2070
2081
  var BACKCHANNEL_LOGOUT_EVENT_CLAIM = "http://schemas.openid.net/event/backchannel-logout";
2071
2082
  var validateBackchannelLogoutTokenTyp = (typ) => {
2072
2083
  if (typ !== void 0 && (typeof typ !== "string" || typ.toLowerCase() !== "logout+jwt")) {
@@ -2228,6 +2239,14 @@ function createOidcVaultJwtAccessTokenValidator(options) {
2228
2239
  const result = await (0, import_jose4.jwtVerify)(token, key, { issuer, audience, algorithms });
2229
2240
  const claims = result.payload;
2230
2241
  const confirmation = snapshotVerifiedJwtConfirmation(claims);
2242
+ if (confirmation !== null) {
2243
+ if (!isCompactSignedJwt(token)) {
2244
+ throw invalidAccessToken("Bound JWT must use canonical compact signed encoding.");
2245
+ }
2246
+ if (readJwtExpirationMs(claims.exp) === void 0) {
2247
+ throw invalidAccessToken("Bound JWT exp must be a nonnegative safe integer with safe milliseconds.");
2248
+ }
2249
+ }
2231
2250
  const mapped = mapClaims ? mapClaims(claims) : defaultJwtClaimsMapper(claims);
2232
2251
  const { subject, sessionId, scope, claims: mappedClaims } = mapped;
2233
2252
  return { subject, sessionId, scope, claims: mappedClaims, confirmation };
package/index.mjs CHANGED
@@ -1785,6 +1785,35 @@ async function fetchUserInfo(metadata, accessToken, options = {}) {
1785
1785
  // src/token-issuance.ts
1786
1786
  import { decodeJwt, decodeProtectedHeader } from "jose";
1787
1787
 
1788
+ // src/access-token-confirmation.ts
1789
+ var invalidAccessToken = (diagnostic) => new OidcVaultHttpError(401, "OIDC_VAULT_INVALID_ACCESS_TOKEN", diagnostic, "Access token validation failed.");
1790
+ var snapshotJkt = (value, invalid = invalidAccessToken) => {
1791
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1792
+ throw invalid("Access token confirmation must be a plain jkt object.");
1793
+ }
1794
+ const prototype = Object.getPrototypeOf(value);
1795
+ const keys = Reflect.ownKeys(value);
1796
+ if (prototype !== Object.prototype && prototype !== null || keys.length !== 1 || keys[0] !== "jkt") {
1797
+ throw invalid("Access token confirmation contains unsupported fields.");
1798
+ }
1799
+ const { jkt } = value;
1800
+ if (!isCanonicalDpopJkt(jkt)) throw invalid("Access token confirmation is not a canonical SHA-256 thumbprint.");
1801
+ return Object.freeze({ jkt });
1802
+ };
1803
+ var isCompactSignedJwt = (token) => {
1804
+ const parts = token.split(".");
1805
+ return parts.length === 3 && parts.every(
1806
+ (part) => /^[A-Za-z0-9_-]+$/.test(part) ? Buffer.from(part, "base64url").toString("base64url") === part : false
1807
+ );
1808
+ };
1809
+ var readJwtExpirationMs = (exp) => {
1810
+ if (typeof exp !== "number" || !Number.isSafeInteger(exp) || exp < 0) return void 0;
1811
+ const milliseconds = exp * 1e3;
1812
+ return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;
1813
+ };
1814
+ var snapshotVerifiedJwtConfirmation = (claims) => Object.hasOwn(claims, "cnf") ? snapshotJkt(claims.cnf) : null;
1815
+ var snapshotAccessTokenConfirmation = (value) => value === null ? null : snapshotJkt(value);
1816
+
1788
1817
  // src/vault-session.ts
1789
1818
  var invalidVaultSession = () => new OidcVaultHttpError(401, "OIDC_VAULT_INVALID_SESSION", "Session is missing or expired.");
1790
1819
  var invalidExchangeCode = () => new OidcVaultHttpError(400, "OIDC_VAULT_INVALID_EXCHANGE_CODE", "Exchange code is invalid or expired.");
@@ -1929,13 +1958,7 @@ var createExchangeResponse = (options, session, issuedToken) => ({
1929
1958
  expiresIn: issuedToken.expiresIn,
1930
1959
  tokenType: issuedToken.tokenType
1931
1960
  });
1932
- var isCompactSignedJwt = (token) => {
1933
- const parts = token.split(".");
1934
- return parts.length === 3 && parts.every(
1935
- (part) => /^[A-Za-z0-9_-]+$/.test(part) ? Buffer.from(part, "base64url").toString("base64url") === part : false
1936
- );
1937
- };
1938
- var assertIssuedTokenConfirmation = (accessToken, jkt) => {
1961
+ var assertIssuedBoundJwt = (accessToken, jkt) => {
1939
1962
  if (!isCompactSignedJwt(accessToken)) {
1940
1963
  throw new TypeError("tokenIssuer.issue accessToken must be a compact signed JWT for bound issuance.");
1941
1964
  }
@@ -1950,10 +1973,16 @@ var assertIssuedTokenConfirmation = (accessToken, jkt) => {
1950
1973
  if (typeof header.alg !== "string" || header.alg.length === 0 || header.alg === "none" || header.b64 === false) {
1951
1974
  throw new TypeError("tokenIssuer.issue accessToken must use a signed JWT algorithm for bound issuance.");
1952
1975
  }
1953
- const cnf = claims.cnf;
1954
- if (typeof cnf !== "object" || cnf === null || Array.isArray(cnf) || cnf.jkt !== jkt) {
1976
+ const confirmation = snapshotJkt(
1977
+ claims.cnf,
1978
+ (diagnostic) => new TypeError(`tokenIssuer.issue accessToken cnf.jkt is invalid. ${diagnostic}`)
1979
+ );
1980
+ if (confirmation.jkt !== jkt) {
1955
1981
  throw new TypeError("tokenIssuer.issue accessToken cnf.jkt must match the verified device binding.");
1956
1982
  }
1983
+ if (readJwtExpirationMs(claims.exp) === void 0) {
1984
+ throw new TypeError("tokenIssuer.issue accessToken exp must be a nonnegative safe integer with safe milliseconds.");
1985
+ }
1957
1986
  };
1958
1987
  var withIssuedToken = async (req, res, options, session, verifiedBinding) => {
1959
1988
  const binding = resolveVerifiedDeviceBinding(options.deviceBinding, session.deviceBinding, verifiedBinding);
@@ -1986,7 +2015,10 @@ var withIssuedToken = async (req, res, options, session, verifiedBinding) => {
1986
2015
  }
1987
2016
  } else {
1988
2017
  if (tokenType !== "DPoP") throw new TypeError("tokenIssuer.issue tokenType must be DPoP for bound issuance.");
1989
- assertIssuedTokenConfirmation(accessToken, binding.jkt);
2018
+ if (!Number.isSafeInteger(expiresIn * 1e3)) {
2019
+ throw new TypeError("tokenIssuer.issue expiresIn must have safe milliseconds for bound issuance.");
2020
+ }
2021
+ assertIssuedBoundJwt(accessToken, binding.jkt);
1990
2022
  }
1991
2023
  return { accessToken, expiresIn, ...tokenType === void 0 ? {} : { tokenType } };
1992
2024
  } catch (error) {
@@ -1998,27 +2030,6 @@ var withIssuedToken = async (req, res, options, session, verifiedBinding) => {
1998
2030
 
1999
2031
  // src/token-validation.ts
2000
2032
  import { jwtVerify } from "jose";
2001
-
2002
- // src/access-token-confirmation.ts
2003
- var invalidAccessToken = (diagnostic) => new OidcVaultHttpError(401, "OIDC_VAULT_INVALID_ACCESS_TOKEN", diagnostic, "Access token validation failed.");
2004
- var snapshotJkt = (value) => {
2005
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
2006
- throw invalidAccessToken("Access token confirmation must be a plain jkt object.");
2007
- }
2008
- const prototype = Object.getPrototypeOf(value);
2009
- const keys = Reflect.ownKeys(value);
2010
- if (prototype !== Object.prototype && prototype !== null || keys.length !== 1 || keys[0] !== "jkt") {
2011
- throw invalidAccessToken("Access token confirmation contains unsupported fields.");
2012
- }
2013
- const { jkt } = value;
2014
- if (!isCanonicalDpopJkt(jkt))
2015
- throw invalidAccessToken("Access token confirmation is not a canonical SHA-256 thumbprint.");
2016
- return Object.freeze({ jkt });
2017
- };
2018
- var snapshotVerifiedJwtConfirmation = (claims) => Object.hasOwn(claims, "cnf") ? snapshotJkt(claims.cnf) : null;
2019
- var snapshotAccessTokenConfirmation = (value) => value === null ? null : snapshotJkt(value);
2020
-
2021
- // src/token-validation.ts
2022
2033
  var BACKCHANNEL_LOGOUT_EVENT_CLAIM = "http://schemas.openid.net/event/backchannel-logout";
2023
2034
  var validateBackchannelLogoutTokenTyp = (typ) => {
2024
2035
  if (typ !== void 0 && (typeof typ !== "string" || typ.toLowerCase() !== "logout+jwt")) {
@@ -2180,6 +2191,14 @@ function createOidcVaultJwtAccessTokenValidator(options) {
2180
2191
  const result = await jwtVerify(token, key, { issuer, audience, algorithms });
2181
2192
  const claims = result.payload;
2182
2193
  const confirmation = snapshotVerifiedJwtConfirmation(claims);
2194
+ if (confirmation !== null) {
2195
+ if (!isCompactSignedJwt(token)) {
2196
+ throw invalidAccessToken("Bound JWT must use canonical compact signed encoding.");
2197
+ }
2198
+ if (readJwtExpirationMs(claims.exp) === void 0) {
2199
+ throw invalidAccessToken("Bound JWT exp must be a nonnegative safe integer with safe milliseconds.");
2200
+ }
2201
+ }
2183
2202
  const mapped = mapClaims ? mapClaims(claims) : defaultJwtClaimsMapper(claims);
2184
2203
  const { subject, sessionId, scope, claims: mappedClaims } = mapped;
2185
2204
  return { subject, sessionId, scope, claims: mappedClaims, confirmation };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@web-ts-toolkit/express-oidc-vault",
3
3
  "description": "Express OIDC sessions with body or cookie transport, optional DPoP-bound local JWTs, and pluggable vault stores",
4
4
  "homepage": "https://web-ts-toolkit.pages.dev/docs/packages/express-oidc-vault",
5
- "version": "0.51.0",
5
+ "version": "0.52.0",
6
6
  "sideEffects": false,
7
7
  "keywords": [
8
8
  "express",
@@ -26,6 +26,16 @@
26
26
  "import": "./index.mjs",
27
27
  "require": "./index.js",
28
28
  "default": "./index.js"
29
+ },
30
+ "./wire": {
31
+ "types": {
32
+ "import": "./wire.d.mts",
33
+ "require": "./wire.d.ts",
34
+ "default": "./wire.d.ts"
35
+ },
36
+ "import": "./wire.mjs",
37
+ "require": "./wire.js",
38
+ "default": "./wire.js"
29
39
  }
30
40
  },
31
41
  "engines": {
package/wire.d.mts ADDED
@@ -0,0 +1,76 @@
1
+ /** Public JSON profile returned by exchange/refresh. */
2
+ interface OidcVaultUserProfile {
3
+ sub: string;
4
+ email?: string;
5
+ name?: string;
6
+ preferredUsername?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ /**
10
+ * Local application credentials returned by `OidcVaultTokenIssuer.issue`.
11
+ * Runtime validation copies only these fields into a fresh result; additional
12
+ * properties are ignored and cannot override the response's session ID/user.
13
+ */
14
+ interface OidcVaultTokenIssueResult {
15
+ /**
16
+ * Nonempty opaque token for unbound issuance. Bound issuance requires a
17
+ * compact signed JWT (canonical unpadded base64url), exactly one cnf field
18
+ * `{ jkt }` matching the verified canonical SHA-256 thumbprint, and a
19
+ * nonnegative safe-integer exp in seconds with safe exp * 1000 milliseconds.
20
+ * Core checks the output shape; APIs independently authenticate the JWT.
21
+ */
22
+ accessToken: string;
23
+ /**
24
+ * Token lifetime in seconds: a finite nonnegative safe integer; bound
25
+ * issuance also requires safe expiresIn * 1000. Zero is valid and may carry
26
+ * a rotated session handle, but supplies no live reusable API credential.
27
+ */
28
+ expiresIn: number;
29
+ /** Exact `DPoP` is required when bound. Unbound permits only `Bearer` or omission; omitted/undefined stays absent in JSON. */
30
+ tokenType?: 'Bearer' | 'DPoP';
31
+ }
32
+ /** Exchange/refresh JSON. Local token fields are absent when no token issuer is configured. */
33
+ interface OidcVaultExchangeResult extends Partial<OidcVaultTokenIssueResult> {
34
+ /** Authoritative vault handle in body transport; omitted from cookie-transport JSON. */
35
+ sessionId?: string;
36
+ /** Session profile; extra token-issuer result properties cannot override it. */
37
+ user?: OidcVaultUserProfile;
38
+ }
39
+ /** JSON body for opt-in `POST <basePath>/login`; proof/key and recognition signals belong in their configured headers, not the body. */
40
+ interface OidcVaultLoginInitiationInput {
41
+ /** Optional destination on the configured frontend origin. Query-string returnTo is ignored by POST login. */
42
+ returnTo?: string;
43
+ }
44
+ /**
45
+ * Exact successful POST-login JSON. Navigate to this URL after storing a proof
46
+ * key when DPoP is enabled. Use credentials: 'include' even with body session
47
+ * transport: initiation sets a temporary HttpOnly transaction cookie.
48
+ */
49
+ interface OidcVaultLoginInitiationResult {
50
+ authorizationUrl: string;
51
+ }
52
+ /** Successful local logout; stateless application JWTs require separate revocation or expiry. */
53
+ interface OidcVaultLogoutResult {
54
+ /**
55
+ * Successful logout commits revocation before upstream work and clears the
56
+ * session cookie under cookie transport. Built-in live handles and unexpired
57
+ * aliases authenticate the surviving lineage's provider/original binding;
58
+ * wrong identity, missing/wrong/stale/replayed proof, or disabled acceptance
59
+ * of a bound lineage fails without deleting or clearing. No currently live
60
+ * target is idempotent success without deletion or proof reservation. Aliases
61
+ * grant revocation only, not refresh authentication or upstream redirects.
62
+ * Old custom bearer stores without revocation context retain legacy alias
63
+ * deletion behavior. Stateless application access tokens are not invalidated.
64
+ * Local-only logout (`redirect` unset or `false`) never contacts the provider.
65
+ * Redirected logout (`redirect: true`)
66
+ * treats the upstream end-session redirect as best-effort: when provider
67
+ * discovery fails or no `endSessionEndpoint` is available, the route still
68
+ * returns this local success. Discovery errors reach `onError` without
69
+ * undoing revocation or skipping the live session's `onLogout` notification.
70
+ */
71
+ loggedOut: true;
72
+ }
73
+ /** Vault handle transport; independent of DPoP mode. Default: body. */
74
+ type OidcVaultSessionTransport = 'body' | 'cookie';
75
+
76
+ export type { OidcVaultExchangeResult, OidcVaultLoginInitiationInput, OidcVaultLoginInitiationResult, OidcVaultLogoutResult, OidcVaultSessionTransport, OidcVaultTokenIssueResult, OidcVaultUserProfile };