@openeudi/openid4vp 0.6.0 → 0.8.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/dist/index.d.cts CHANGED
@@ -15,9 +15,49 @@ interface AuthorizationRequest {
15
15
  nonce: string;
16
16
  state: string;
17
17
  }
18
+ interface SignedAuthorizationRequestInput {
19
+ hostname: string;
20
+ requestUri: string;
21
+ responseUri: string;
22
+ nonce: string;
23
+ state?: string;
24
+ responseMode?: 'direct_post' | 'direct_post.jwt';
25
+ signer: CryptoKeyPair;
26
+ signingAlgorithm?: 'ES256' | 'ES384' | 'RS256';
27
+ certificateChain: Uint8Array[];
28
+ encryptionKey?: {
29
+ publicJwk: JsonWebKey;
30
+ supportedEncValues?: string[];
31
+ };
32
+ vpFormatsSupported: Record<string, unknown>;
33
+ }
34
+ interface SignedAuthorizationRequest {
35
+ uri: string;
36
+ requestObject: string;
37
+ dcqlQuery: DcqlQuery;
38
+ nonce: string;
39
+ state: string;
40
+ }
41
+ interface AuthorizationResponse {
42
+ vp_token: Record<string, Array<string | object>>;
43
+ state?: string;
44
+ [key: string]: unknown;
45
+ }
18
46
 
19
47
  declare function createAuthorizationRequest(input: AuthorizationRequestInput, query: DcqlQuery): AuthorizationRequest;
20
48
 
49
+ /**
50
+ * Build a signed authorization request (JAR) per OpenID4VP 1.0 §5.10 / RFC 9101.
51
+ *
52
+ * Validates that the signing key is bound to the leaf certificate and that the
53
+ * leaf cert's SAN DNSName equals the declared hostname. Emits a short URI
54
+ * carrying only `client_id` + `request_uri`, plus the JWS string the caller
55
+ * must host at `requestUri` with Content-Type `application/oauth-authz-req+jwt`.
56
+ *
57
+ * Client Identifier Prefix is always `x509_san_dns` — other prefixes deferred.
58
+ */
59
+ declare function createSignedAuthorizationRequest(input: SignedAuthorizationRequestInput, query: DcqlQuery): Promise<SignedAuthorizationRequest>;
60
+
21
61
  interface HaipQueryInput {
22
62
  credentialId: string;
23
63
  format: 'dc+sd-jwt' | 'mso_mdoc';
@@ -277,6 +317,27 @@ interface ParseOptions {
277
317
  cache?: Cache;
278
318
  /** Clock-skew tolerance in seconds for certificate validity checks. Default 60. */
279
319
  clockSkewTolerance?: number;
320
+ /**
321
+ * An explicit set of trusted issuer JWKs used as an alternate trust path when the
322
+ * SD-JWT VC's issuer JWT lacks an `x5c` header. When the header has no `x5c`:
323
+ * - If this array is provided, the parser looks up the issuer key by `kid`
324
+ * (or by exact `kty`/`crv`/`x`/`y` match when no `kid` is present). The
325
+ * matched JWK is the trust anchor — cert-chain validation is skipped.
326
+ * - If this array is absent (or empty), the parser falls back to the existing
327
+ * behaviour and throws `MalformedCredentialError('Missing or invalid x5c in JWT header')`.
328
+ *
329
+ * **When the JWT header DOES include `x5c`** this option is ignored — the existing
330
+ * x5c/`trustedCertificates` / `trustStore` path runs unchanged.
331
+ *
332
+ * **Security notice**: opting in to this path skips certificate-chain trust
333
+ * evaluation entirely. The caller is explicitly asserting that they trust the
334
+ * supplied JWK(s) out-of-band. This is appropriate for CI harness setups (e.g.
335
+ * OIDF conformance suite, where the wallet signs without x5c and the verifier
336
+ * knows the signing key from the test-plan config). It is **not recommended for
337
+ * production verifiers** — cert-chain trust evaluation via `trustStore` is the
338
+ * secure path.
339
+ */
340
+ trustedIssuerJwks?: JsonWebKey[];
280
341
  }
281
342
  interface ICredentialParser {
282
343
  readonly format: CredentialFormat;
@@ -293,6 +354,12 @@ interface VerifyResult {
293
354
  submission: DcqlSubmission | null;
294
355
  valid: boolean;
295
356
  }
357
+ interface EncryptedResponse {
358
+ response: string;
359
+ }
360
+ type VerifyAuthorizationResponseOptions = VerifyOptions & {
361
+ decryptionKey?: CryptoKey;
362
+ };
296
363
 
297
364
  /**
298
365
  * Parses a VP token, then matches it against a DCQL query.
@@ -306,6 +373,34 @@ interface VerifyResult {
306
373
  * @param options parse + verify options (nonce, trusted issuers, etc.)
307
374
  */
308
375
  declare function verifyPresentation(vpToken: unknown, query: DcqlQuery, options: VerifyOptions): Promise<VerifyResult>;
376
+ /**
377
+ * Verify an OpenID4VP 1.0 §8.1 Authorization Response envelope.
378
+ *
379
+ * Accepts either the unencrypted envelope (object-keyed `vp_token`) or a
380
+ * JWE-wrapped envelope `{ response: '<JWE>' }` for response_mode =
381
+ * direct_post.jwt. When encrypted, decrypts with `options.decryptionKey`
382
+ * first. For this release only single-credential single-presentation is
383
+ * supported — multi-credential envelopes throw
384
+ * {@link MultipleCredentialsNotSupportedError}. Otherwise delegates the
385
+ * extracted single presentation to the existing {@link verifyPresentation}.
386
+ *
387
+ * Callers MUST compare the envelope's `state` against the value they issued
388
+ * themselves — library is stateless and does not track state.
389
+ */
390
+ declare function verifyAuthorizationResponse(envelope: AuthorizationResponse | EncryptedResponse, query: DcqlQuery, options: VerifyAuthorizationResponseOptions): Promise<VerifyResult>;
391
+
392
+ /**
393
+ * Decrypt a JWE-wrapped OpenID4VP Authorization Response (response_mode =
394
+ * direct_post.jwt). Returns the inner §8.1 envelope.
395
+ *
396
+ * Supported JWE algorithms (others throw UnsupportedJweError):
397
+ * - alg: ECDH-ES
398
+ * - enc: A128GCM, A256GCM (HAIP requires both)
399
+ *
400
+ * Cryptographic failures (wrong key, tampered ciphertext) throw
401
+ * DecryptionFailedError.
402
+ */
403
+ declare function decryptAuthorizationResponse(jwe: string, privateKey: CryptoKey): Promise<AuthorizationResponse>;
309
404
 
310
405
  /**
311
406
  * SD-JWT VC credential parser.
@@ -416,6 +511,33 @@ declare class LotlFetchError extends OpenID4VPError {
416
511
  declare class LotlSignatureError extends OpenID4VPError {
417
512
  readonly code: "lotl_signature_invalid";
418
513
  }
514
+ type SignedRequestBuildErrorCode = 'empty_cert_chain' | 'hostname_cert_mismatch' | 'signing_key_cert_mismatch' | 'missing_encryption_jwk' | 'missing_encryption_alg' | 'missing_vp_formats' | 'unsupported_signing_alg' | 'empty_supported_enc_values';
515
+ declare class SignedRequestBuildError extends OpenID4VPError {
516
+ readonly code: SignedRequestBuildErrorCode;
517
+ constructor(code: SignedRequestBuildErrorCode, message: string);
518
+ }
519
+ declare class UnsupportedJweError extends OpenID4VPError {
520
+ readonly code: "unsupported_jwe";
521
+ readonly alg: string;
522
+ readonly enc: string;
523
+ constructor(alg: string, enc: string);
524
+ }
525
+ declare class DecryptionFailedError extends OpenID4VPError {
526
+ readonly code: "decryption_failed";
527
+ constructor(message?: string, options?: {
528
+ cause?: Error;
529
+ });
530
+ }
531
+ declare class MissingDecryptionKeyError extends OpenID4VPError {
532
+ readonly code: "missing_decryption_key";
533
+ constructor(message?: string);
534
+ }
535
+ declare class MultipleCredentialsNotSupportedError extends OpenID4VPError {
536
+ readonly code: "multi_credential_unsupported";
537
+ readonly entryCount: number;
538
+ readonly presentationCount: number;
539
+ constructor(entryCount: number, presentationCount: number);
540
+ }
419
541
 
420
542
  interface LotlTrustStoreOptions {
421
543
  /** Override the bundled signing anchors. Empty is rejected. */
@@ -454,6 +576,6 @@ declare class LotlTrustStore implements TrustStore {
454
576
  private refresh;
455
577
  }
456
578
 
457
- declare const VERSION = "0.5.0";
579
+ declare const VERSION = "0.8.0";
458
580
 
459
- export { type AuthorizationRequest, type AuthorizationRequestInput, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, VERSION, type VerifyOptions, type VerifyResult, buildHaipQuery, createAuthorizationRequest, isHaipQuery, parsePresentation, validateHaipQuery, verifyPresentation };
581
+ export { type AuthorizationRequest, type AuthorizationRequestInput, type AuthorizationResponse, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, DecryptionFailedError, type EncryptedResponse, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, type SignedAuthorizationRequest, type SignedAuthorizationRequestInput, SignedRequestBuildError, type SignedRequestBuildErrorCode, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, UnsupportedJweError, VERSION, type VerifyAuthorizationResponseOptions, type VerifyOptions, type VerifyResult, buildHaipQuery, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
package/dist/index.d.ts CHANGED
@@ -15,9 +15,49 @@ interface AuthorizationRequest {
15
15
  nonce: string;
16
16
  state: string;
17
17
  }
18
+ interface SignedAuthorizationRequestInput {
19
+ hostname: string;
20
+ requestUri: string;
21
+ responseUri: string;
22
+ nonce: string;
23
+ state?: string;
24
+ responseMode?: 'direct_post' | 'direct_post.jwt';
25
+ signer: CryptoKeyPair;
26
+ signingAlgorithm?: 'ES256' | 'ES384' | 'RS256';
27
+ certificateChain: Uint8Array[];
28
+ encryptionKey?: {
29
+ publicJwk: JsonWebKey;
30
+ supportedEncValues?: string[];
31
+ };
32
+ vpFormatsSupported: Record<string, unknown>;
33
+ }
34
+ interface SignedAuthorizationRequest {
35
+ uri: string;
36
+ requestObject: string;
37
+ dcqlQuery: DcqlQuery;
38
+ nonce: string;
39
+ state: string;
40
+ }
41
+ interface AuthorizationResponse {
42
+ vp_token: Record<string, Array<string | object>>;
43
+ state?: string;
44
+ [key: string]: unknown;
45
+ }
18
46
 
19
47
  declare function createAuthorizationRequest(input: AuthorizationRequestInput, query: DcqlQuery): AuthorizationRequest;
20
48
 
49
+ /**
50
+ * Build a signed authorization request (JAR) per OpenID4VP 1.0 §5.10 / RFC 9101.
51
+ *
52
+ * Validates that the signing key is bound to the leaf certificate and that the
53
+ * leaf cert's SAN DNSName equals the declared hostname. Emits a short URI
54
+ * carrying only `client_id` + `request_uri`, plus the JWS string the caller
55
+ * must host at `requestUri` with Content-Type `application/oauth-authz-req+jwt`.
56
+ *
57
+ * Client Identifier Prefix is always `x509_san_dns` — other prefixes deferred.
58
+ */
59
+ declare function createSignedAuthorizationRequest(input: SignedAuthorizationRequestInput, query: DcqlQuery): Promise<SignedAuthorizationRequest>;
60
+
21
61
  interface HaipQueryInput {
22
62
  credentialId: string;
23
63
  format: 'dc+sd-jwt' | 'mso_mdoc';
@@ -277,6 +317,27 @@ interface ParseOptions {
277
317
  cache?: Cache;
278
318
  /** Clock-skew tolerance in seconds for certificate validity checks. Default 60. */
279
319
  clockSkewTolerance?: number;
320
+ /**
321
+ * An explicit set of trusted issuer JWKs used as an alternate trust path when the
322
+ * SD-JWT VC's issuer JWT lacks an `x5c` header. When the header has no `x5c`:
323
+ * - If this array is provided, the parser looks up the issuer key by `kid`
324
+ * (or by exact `kty`/`crv`/`x`/`y` match when no `kid` is present). The
325
+ * matched JWK is the trust anchor — cert-chain validation is skipped.
326
+ * - If this array is absent (or empty), the parser falls back to the existing
327
+ * behaviour and throws `MalformedCredentialError('Missing or invalid x5c in JWT header')`.
328
+ *
329
+ * **When the JWT header DOES include `x5c`** this option is ignored — the existing
330
+ * x5c/`trustedCertificates` / `trustStore` path runs unchanged.
331
+ *
332
+ * **Security notice**: opting in to this path skips certificate-chain trust
333
+ * evaluation entirely. The caller is explicitly asserting that they trust the
334
+ * supplied JWK(s) out-of-band. This is appropriate for CI harness setups (e.g.
335
+ * OIDF conformance suite, where the wallet signs without x5c and the verifier
336
+ * knows the signing key from the test-plan config). It is **not recommended for
337
+ * production verifiers** — cert-chain trust evaluation via `trustStore` is the
338
+ * secure path.
339
+ */
340
+ trustedIssuerJwks?: JsonWebKey[];
280
341
  }
281
342
  interface ICredentialParser {
282
343
  readonly format: CredentialFormat;
@@ -293,6 +354,12 @@ interface VerifyResult {
293
354
  submission: DcqlSubmission | null;
294
355
  valid: boolean;
295
356
  }
357
+ interface EncryptedResponse {
358
+ response: string;
359
+ }
360
+ type VerifyAuthorizationResponseOptions = VerifyOptions & {
361
+ decryptionKey?: CryptoKey;
362
+ };
296
363
 
297
364
  /**
298
365
  * Parses a VP token, then matches it against a DCQL query.
@@ -306,6 +373,34 @@ interface VerifyResult {
306
373
  * @param options parse + verify options (nonce, trusted issuers, etc.)
307
374
  */
308
375
  declare function verifyPresentation(vpToken: unknown, query: DcqlQuery, options: VerifyOptions): Promise<VerifyResult>;
376
+ /**
377
+ * Verify an OpenID4VP 1.0 §8.1 Authorization Response envelope.
378
+ *
379
+ * Accepts either the unencrypted envelope (object-keyed `vp_token`) or a
380
+ * JWE-wrapped envelope `{ response: '<JWE>' }` for response_mode =
381
+ * direct_post.jwt. When encrypted, decrypts with `options.decryptionKey`
382
+ * first. For this release only single-credential single-presentation is
383
+ * supported — multi-credential envelopes throw
384
+ * {@link MultipleCredentialsNotSupportedError}. Otherwise delegates the
385
+ * extracted single presentation to the existing {@link verifyPresentation}.
386
+ *
387
+ * Callers MUST compare the envelope's `state` against the value they issued
388
+ * themselves — library is stateless and does not track state.
389
+ */
390
+ declare function verifyAuthorizationResponse(envelope: AuthorizationResponse | EncryptedResponse, query: DcqlQuery, options: VerifyAuthorizationResponseOptions): Promise<VerifyResult>;
391
+
392
+ /**
393
+ * Decrypt a JWE-wrapped OpenID4VP Authorization Response (response_mode =
394
+ * direct_post.jwt). Returns the inner §8.1 envelope.
395
+ *
396
+ * Supported JWE algorithms (others throw UnsupportedJweError):
397
+ * - alg: ECDH-ES
398
+ * - enc: A128GCM, A256GCM (HAIP requires both)
399
+ *
400
+ * Cryptographic failures (wrong key, tampered ciphertext) throw
401
+ * DecryptionFailedError.
402
+ */
403
+ declare function decryptAuthorizationResponse(jwe: string, privateKey: CryptoKey): Promise<AuthorizationResponse>;
309
404
 
310
405
  /**
311
406
  * SD-JWT VC credential parser.
@@ -416,6 +511,33 @@ declare class LotlFetchError extends OpenID4VPError {
416
511
  declare class LotlSignatureError extends OpenID4VPError {
417
512
  readonly code: "lotl_signature_invalid";
418
513
  }
514
+ type SignedRequestBuildErrorCode = 'empty_cert_chain' | 'hostname_cert_mismatch' | 'signing_key_cert_mismatch' | 'missing_encryption_jwk' | 'missing_encryption_alg' | 'missing_vp_formats' | 'unsupported_signing_alg' | 'empty_supported_enc_values';
515
+ declare class SignedRequestBuildError extends OpenID4VPError {
516
+ readonly code: SignedRequestBuildErrorCode;
517
+ constructor(code: SignedRequestBuildErrorCode, message: string);
518
+ }
519
+ declare class UnsupportedJweError extends OpenID4VPError {
520
+ readonly code: "unsupported_jwe";
521
+ readonly alg: string;
522
+ readonly enc: string;
523
+ constructor(alg: string, enc: string);
524
+ }
525
+ declare class DecryptionFailedError extends OpenID4VPError {
526
+ readonly code: "decryption_failed";
527
+ constructor(message?: string, options?: {
528
+ cause?: Error;
529
+ });
530
+ }
531
+ declare class MissingDecryptionKeyError extends OpenID4VPError {
532
+ readonly code: "missing_decryption_key";
533
+ constructor(message?: string);
534
+ }
535
+ declare class MultipleCredentialsNotSupportedError extends OpenID4VPError {
536
+ readonly code: "multi_credential_unsupported";
537
+ readonly entryCount: number;
538
+ readonly presentationCount: number;
539
+ constructor(entryCount: number, presentationCount: number);
540
+ }
419
541
 
420
542
  interface LotlTrustStoreOptions {
421
543
  /** Override the bundled signing anchors. Empty is rejected. */
@@ -454,6 +576,6 @@ declare class LotlTrustStore implements TrustStore {
454
576
  private refresh;
455
577
  }
456
578
 
457
- declare const VERSION = "0.5.0";
579
+ declare const VERSION = "0.8.0";
458
580
 
459
- export { type AuthorizationRequest, type AuthorizationRequestInput, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, VERSION, type VerifyOptions, type VerifyResult, buildHaipQuery, createAuthorizationRequest, isHaipQuery, parsePresentation, validateHaipQuery, verifyPresentation };
581
+ export { type AuthorizationRequest, type AuthorizationRequestInput, type AuthorizationResponse, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, DecryptionFailedError, type EncryptedResponse, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, type SignedAuthorizationRequest, type SignedAuthorizationRequestInput, SignedRequestBuildError, type SignedRequestBuildErrorCode, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, UnsupportedJweError, VERSION, type VerifyAuthorizationResponseOptions, type VerifyOptions, type VerifyResult, buildHaipQuery, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };