@gramota/oid4vp 0.2.1 → 0.3.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/cert.d.ts +57 -1
- package/dist/cert.d.ts.map +1 -1
- package/dist/cert.js +84 -2
- package/dist/cert.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/jar.d.ts +42 -2
- package/dist/jar.d.ts.map +1 -1
- package/dist/jar.js +47 -2
- package/dist/jar.js.map +1 -1
- package/dist/random.d.ts +45 -0
- package/dist/random.d.ts.map +1 -0
- package/dist/random.js +50 -0
- package/dist/random.js.map +1 -0
- package/dist/response-jwt.d.ts +145 -0
- package/dist/response-jwt.d.ts.map +1 -0
- package/dist/response-jwt.js +295 -0
- package/dist/response-jwt.js.map +1 -0
- package/dist/types.d.ts +7 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
package/dist/cert.d.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import "reflect-metadata";
|
|
20
20
|
import type { JsonWebKey } from "@gramota/jose";
|
|
21
|
-
import { type SigningCert } from "./types.js";
|
|
21
|
+
import { type ClientIdScheme, type SigningCert } from "./types.js";
|
|
22
22
|
export interface GenerateSigningCertOptions {
|
|
23
23
|
/** Primary DNS name for the cert's Subject Alternative Name. Must match
|
|
24
24
|
* the verifier's hostname (the part the wallet sees in the OID4VP
|
|
@@ -69,4 +69,60 @@ export declare function signingCertToJwks(cert: SigningCert): Promise<{
|
|
|
69
69
|
publicJwk: JsonWebKey;
|
|
70
70
|
privateJwk: JsonWebKey;
|
|
71
71
|
}>;
|
|
72
|
+
/**
|
|
73
|
+
* Compute the `x509_hash` digest of a signing cert per OID4VP §5.9.3 +
|
|
74
|
+
* HAIP Final 1.0 §5: `base64url(SHA-256(DER-encoded leaf certificate))`.
|
|
75
|
+
*
|
|
76
|
+
* The leaf cert's DER bytes are taken from the first entry of {@link
|
|
77
|
+
* SigningCert.x5c}. That entry is already base64-encoded DER (no PEM
|
|
78
|
+
* armour) — we decode, hash, and base64url-encode the digest.
|
|
79
|
+
*
|
|
80
|
+
* The result becomes the value part of the `x509_hash:<digest>` Client
|
|
81
|
+
* Identifier. Wallets that see this prefix:
|
|
82
|
+
* 1. Read the JWS `x5c` header.
|
|
83
|
+
* 2. Compute the same hash over the leaf cert.
|
|
84
|
+
* 3. Compare against the value portion of `client_id`.
|
|
85
|
+
* 4. If they match, the cert is the verifier's authentic key.
|
|
86
|
+
*
|
|
87
|
+
* Unlike `x509_san_dns`, the cert's SAN is not consulted — the cert
|
|
88
|
+
* itself, via its hash, IS the identity. This makes the prefix the
|
|
89
|
+
* spec-preferred form for HAIP Final 1.0: an attacker who steals the
|
|
90
|
+
* `client_id` cannot substitute a different (same-SAN) cert.
|
|
91
|
+
*
|
|
92
|
+
* @throws {@link Oid4vpError} `oid4vp.cert_generation_failed` when the
|
|
93
|
+
* cert's `x5c` is missing or the leaf bytes are malformed base64.
|
|
94
|
+
*/
|
|
95
|
+
export declare function computeCertX509Hash(cert: SigningCert): string;
|
|
96
|
+
/** Schemes {@link buildClientIdFromCert} can construct. */
|
|
97
|
+
export type CertBackedClientIdScheme = "x509_san_dns" | "x509_hash";
|
|
98
|
+
export interface BuildClientIdFromCertOptions {
|
|
99
|
+
/** Signing material the verifier already provisioned. */
|
|
100
|
+
readonly cert: SigningCert;
|
|
101
|
+
/** Prefix to emit. Default `"x509_hash"` — HAIP Final 1.0 §5 mandates
|
|
102
|
+
* this prefix for production HAIP-conformant verifiers. Use
|
|
103
|
+
* `"x509_san_dns"` only for legacy / emulator interop where the wallet
|
|
104
|
+
* doesn't yet accept `x509_hash`. */
|
|
105
|
+
readonly scheme?: CertBackedClientIdScheme;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Build the OID4VP `client_id` for a cert-backed verifier.
|
|
109
|
+
*
|
|
110
|
+
* Returns the prefixed identifier per OID4VP §5.9.3:
|
|
111
|
+
*
|
|
112
|
+
* - `x509_san_dns:<sanDns>` — legacy. Wallet looks up the cert's SAN
|
|
113
|
+
* DNS entry; useful when wallets pre-resolve identity by hostname.
|
|
114
|
+
* - `x509_hash:<base64url(sha256(DER(leaf)))>` — HAIP Final 1.0 §5
|
|
115
|
+
* bullet 3 (MUST for HAIP-conformant verifiers). Wallet hashes the
|
|
116
|
+
* leaf cert in the JWS `x5c` header and compares — no DNS coupling.
|
|
117
|
+
*
|
|
118
|
+
* Pair the returned `client_id` with the matching {@link ClientIdScheme}
|
|
119
|
+
* literal when populating an {@link AuthorizationRequest}.
|
|
120
|
+
*
|
|
121
|
+
* @throws {@link Oid4vpError} `oid4vp.cert_generation_failed` for an
|
|
122
|
+
* unknown scheme, missing SAN-DNS, or malformed `x5c`.
|
|
123
|
+
*/
|
|
124
|
+
export declare function buildClientIdFromCert(options: BuildClientIdFromCertOptions): {
|
|
125
|
+
clientId: string;
|
|
126
|
+
scheme: ClientIdScheme;
|
|
127
|
+
};
|
|
72
128
|
//# sourceMappingURL=cert.d.ts.map
|
package/dist/cert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cert.d.ts","sourceRoot":"","sources":["../src/cert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,kBAAkB,CAAC;AAI1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"cert.d.ts","sourceRoot":"","sources":["../src/cert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,kBAAkB,CAAC;AAI1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAcpB,MAAM,WAAW,0BAA0B;IACzC;;wDAEoD;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;iDAE6C;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;sBACkB;IAClB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,qCAAqC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,WAAW,CAAC,CAyFtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,CAmC5D;AA2CD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAgC7D;AAED,2DAA2D;AAC3D,MAAM,MAAM,wBAAwB,GAAG,cAAc,GAAG,WAAW,CAAC;AAEpE,MAAM,WAAW,4BAA4B;IAC3C,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;;yCAGqC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,4BAA4B,GACpC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAyB9C"}
|
package/dist/cert.js
CHANGED
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
// `dist/cert.js` as a side-effecting module so bundlers don't drop it.
|
|
23
23
|
import "reflect-metadata";
|
|
24
24
|
import * as x509 from "@peculiar/x509";
|
|
25
|
-
import { webcrypto } from "node:crypto";
|
|
25
|
+
import { createHash, webcrypto } from "node:crypto";
|
|
26
26
|
import { exportJWK, importPKCS8, importX509 } from "jose";
|
|
27
|
-
import { Oid4vpError } from "./types.js";
|
|
27
|
+
import { Oid4vpError, } from "./types.js";
|
|
28
28
|
// @peculiar/x509 needs a Web Crypto provider — Node's webcrypto suffices.
|
|
29
29
|
// Safe to call multiple times; no-op after first.
|
|
30
30
|
let cryptoProviderSet = false;
|
|
@@ -188,4 +188,86 @@ function derToPem(der, label) {
|
|
|
188
188
|
function bytesToBase64(bytes) {
|
|
189
189
|
return Buffer.from(bytes).toString("base64");
|
|
190
190
|
}
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
// Client Identifier Prefixes — OID4VP §5.9.3, HAIP Final 1.0 §5.
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
/**
|
|
195
|
+
* Compute the `x509_hash` digest of a signing cert per OID4VP §5.9.3 +
|
|
196
|
+
* HAIP Final 1.0 §5: `base64url(SHA-256(DER-encoded leaf certificate))`.
|
|
197
|
+
*
|
|
198
|
+
* The leaf cert's DER bytes are taken from the first entry of {@link
|
|
199
|
+
* SigningCert.x5c}. That entry is already base64-encoded DER (no PEM
|
|
200
|
+
* armour) — we decode, hash, and base64url-encode the digest.
|
|
201
|
+
*
|
|
202
|
+
* The result becomes the value part of the `x509_hash:<digest>` Client
|
|
203
|
+
* Identifier. Wallets that see this prefix:
|
|
204
|
+
* 1. Read the JWS `x5c` header.
|
|
205
|
+
* 2. Compute the same hash over the leaf cert.
|
|
206
|
+
* 3. Compare against the value portion of `client_id`.
|
|
207
|
+
* 4. If they match, the cert is the verifier's authentic key.
|
|
208
|
+
*
|
|
209
|
+
* Unlike `x509_san_dns`, the cert's SAN is not consulted — the cert
|
|
210
|
+
* itself, via its hash, IS the identity. This makes the prefix the
|
|
211
|
+
* spec-preferred form for HAIP Final 1.0: an attacker who steals the
|
|
212
|
+
* `client_id` cannot substitute a different (same-SAN) cert.
|
|
213
|
+
*
|
|
214
|
+
* @throws {@link Oid4vpError} `oid4vp.cert_generation_failed` when the
|
|
215
|
+
* cert's `x5c` is missing or the leaf bytes are malformed base64.
|
|
216
|
+
*/
|
|
217
|
+
export function computeCertX509Hash(cert) {
|
|
218
|
+
if (cert === null ||
|
|
219
|
+
typeof cert !== "object" ||
|
|
220
|
+
!Array.isArray(cert.x5c) ||
|
|
221
|
+
cert.x5c.length === 0 ||
|
|
222
|
+
typeof cert.x5c[0] !== "string" ||
|
|
223
|
+
cert.x5c[0].length === 0) {
|
|
224
|
+
throw new Oid4vpError("oid4vp.cert_generation_failed", "computeCertX509Hash: cert.x5c[0] must be a non-empty base64-DER string");
|
|
225
|
+
}
|
|
226
|
+
let der;
|
|
227
|
+
try {
|
|
228
|
+
der = Buffer.from(cert.x5c[0], "base64");
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
throw new Oid4vpError("oid4vp.cert_generation_failed", `computeCertX509Hash: failed to decode cert.x5c[0]: ${err instanceof Error ? err.message : String(err)}`);
|
|
232
|
+
}
|
|
233
|
+
if (der.length === 0) {
|
|
234
|
+
throw new Oid4vpError("oid4vp.cert_generation_failed", "computeCertX509Hash: cert.x5c[0] decoded to zero bytes");
|
|
235
|
+
}
|
|
236
|
+
return createHash("sha256").update(der).digest("base64url");
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Build the OID4VP `client_id` for a cert-backed verifier.
|
|
240
|
+
*
|
|
241
|
+
* Returns the prefixed identifier per OID4VP §5.9.3:
|
|
242
|
+
*
|
|
243
|
+
* - `x509_san_dns:<sanDns>` — legacy. Wallet looks up the cert's SAN
|
|
244
|
+
* DNS entry; useful when wallets pre-resolve identity by hostname.
|
|
245
|
+
* - `x509_hash:<base64url(sha256(DER(leaf)))>` — HAIP Final 1.0 §5
|
|
246
|
+
* bullet 3 (MUST for HAIP-conformant verifiers). Wallet hashes the
|
|
247
|
+
* leaf cert in the JWS `x5c` header and compares — no DNS coupling.
|
|
248
|
+
*
|
|
249
|
+
* Pair the returned `client_id` with the matching {@link ClientIdScheme}
|
|
250
|
+
* literal when populating an {@link AuthorizationRequest}.
|
|
251
|
+
*
|
|
252
|
+
* @throws {@link Oid4vpError} `oid4vp.cert_generation_failed` for an
|
|
253
|
+
* unknown scheme, missing SAN-DNS, or malformed `x5c`.
|
|
254
|
+
*/
|
|
255
|
+
export function buildClientIdFromCert(options) {
|
|
256
|
+
const scheme = options.scheme ?? "x509_hash";
|
|
257
|
+
if (scheme === "x509_san_dns") {
|
|
258
|
+
if (typeof options.cert?.sanDns !== "string" ||
|
|
259
|
+
options.cert.sanDns.length === 0) {
|
|
260
|
+
throw new Oid4vpError("oid4vp.cert_generation_failed", "buildClientIdFromCert(x509_san_dns): cert.sanDns is required");
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
clientId: `x509_san_dns:${options.cert.sanDns}`,
|
|
264
|
+
scheme: "x509_san_dns",
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (scheme === "x509_hash") {
|
|
268
|
+
const digest = computeCertX509Hash(options.cert);
|
|
269
|
+
return { clientId: `x509_hash:${digest}`, scheme: "x509_hash" };
|
|
270
|
+
}
|
|
271
|
+
throw new Oid4vpError("oid4vp.cert_generation_failed", `buildClientIdFromCert: unknown scheme ${JSON.stringify(scheme)}`);
|
|
272
|
+
}
|
|
191
273
|
//# sourceMappingURL=cert.js.map
|
package/dist/cert.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cert.js","sourceRoot":"","sources":["../src/cert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,wEAAwE;AACxE,sEAAsE;AACtE,oEAAoE;AACpE,uEAAuE;AACvE,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cert.js","sourceRoot":"","sources":["../src/cert.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { buildAuthorizationRequestUrl, parseAuthorizationRequestUrl, parseAuthorizationRequestSearchParams, } from "./request.js";
|
|
2
2
|
export { buildAuthorizationResponseBody, parseAuthorizationResponseBody, parseAuthorizationResponseFromParams, } from "./response.js";
|
|
3
|
-
export { generateSigningCert, signingCertToJwks, type GenerateSigningCertOptions, } from "./cert.js";
|
|
4
|
-
export { signAuthorizationRequest, type SignAuthorizationRequestOptions, } from "./jar.js";
|
|
3
|
+
export { buildClientIdFromCert, computeCertX509Hash, generateSigningCert, signingCertToJwks, type BuildClientIdFromCertOptions, type CertBackedClientIdScheme, type GenerateSigningCertOptions, } from "./cert.js";
|
|
4
|
+
export { DEFAULT_JAR_AUDIENCE, DEFAULT_JAR_LIFETIME_SECONDS, signAuthorizationRequest, type SignAuthorizationRequestOptions, } from "./jar.js";
|
|
5
|
+
export { generateNonce, generateState, } from "./random.js";
|
|
6
|
+
export { DEFAULT_RESPONSE_JWE_ALG, DEFAULT_RESPONSE_JWE_ENC, decryptAuthorizationResponse, encryptAuthorizationResponse, generateResponseEncryptionKey, type DecryptAuthorizationResponseOptions, type DecryptedAuthorizationResponse, type EncryptAuthorizationResponseOptions, type GenerateResponseEncryptionKeyOptions, } from "./response-jwt.js";
|
|
5
7
|
export { Oid4vpError, type AuthorizationRequest, type AuthorizationResponse, type ClientIdScheme, type Oid4vpErrorCode, type ResponseMode, type SigningCert, } from "./types.js";
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,qCAAqC,GACtC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,EAC9B,oCAAoC,GACrC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,0BAA0B,GAChC,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,wBAAwB,EACxB,KAAK,+BAA+B,GACrC,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,WAAW,EACX,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,qCAAqC,GACtC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,EAC9B,oCAAoC,GACrC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,wBAAwB,EACxB,KAAK,+BAA+B,GACrC,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,aAAa,EACb,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,EAC7B,KAAK,mCAAmC,EACxC,KAAK,8BAA8B,EACnC,KAAK,mCAAmC,EACxC,KAAK,oCAAoC,GAC1C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EACX,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { buildAuthorizationRequestUrl, parseAuthorizationRequestUrl, parseAuthorizationRequestSearchParams, } from "./request.js";
|
|
2
2
|
export { buildAuthorizationResponseBody, parseAuthorizationResponseBody, parseAuthorizationResponseFromParams, } from "./response.js";
|
|
3
|
-
export { generateSigningCert, signingCertToJwks, } from "./cert.js";
|
|
4
|
-
export { signAuthorizationRequest, } from "./jar.js";
|
|
3
|
+
export { buildClientIdFromCert, computeCertX509Hash, generateSigningCert, signingCertToJwks, } from "./cert.js";
|
|
4
|
+
export { DEFAULT_JAR_AUDIENCE, DEFAULT_JAR_LIFETIME_SECONDS, signAuthorizationRequest, } from "./jar.js";
|
|
5
|
+
export { generateNonce, generateState, } from "./random.js";
|
|
6
|
+
export { DEFAULT_RESPONSE_JWE_ALG, DEFAULT_RESPONSE_JWE_ENC, decryptAuthorizationResponse, encryptAuthorizationResponse, generateResponseEncryptionKey, } from "./response-jwt.js";
|
|
5
7
|
export { Oid4vpError, } from "./types.js";
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,qCAAqC,GACtC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,EAC9B,oCAAoC,GACrC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,qCAAqC,GACtC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,EAC9B,oCAAoC,GACrC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAIlB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,wBAAwB,GAEzB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,aAAa,EACb,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,GAK9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,GAOZ,MAAM,YAAY,CAAC"}
|
package/dist/jar.d.ts
CHANGED
|
@@ -17,8 +17,27 @@
|
|
|
17
17
|
* For the EUDIW HAIP profile + the EU reference wallet's demo build,
|
|
18
18
|
* `x509_san_dns` (with this signed JAR shape) is the only `client_id_prefix`
|
|
19
19
|
* the wallet accepts. Production verifiers MUST sign their requests.
|
|
20
|
+
*
|
|
21
|
+
* In addition to the OID4VP request claims, the signer always emits the
|
|
22
|
+
* standard JWT claims `aud`, `iat`, `exp` on the JAR payload (RFC 9101
|
|
23
|
+
* §4 recommends them; OID4VP §5.8 mandates `aud`; HAIP-strict wallets
|
|
24
|
+
* reject when any of the three is absent). The audience defaults to the
|
|
25
|
+
* static pseudo-issuer `https://self-issued.me/v2` and the lifetime
|
|
26
|
+
* defaults to 5 minutes — both are configurable per call.
|
|
20
27
|
*/
|
|
21
28
|
import { type AuthorizationRequest, type SigningCert } from "./types.js";
|
|
29
|
+
/** OID4VP §5.8 — default `aud` for the signed JAR. Wallets check `aud`
|
|
30
|
+
* against either their own issuer URL (dynamic discovery) or the static
|
|
31
|
+
* pseudo-issuer `https://self-issued.me/v2`. We don't do dynamic wallet
|
|
32
|
+
* discovery — so the static value is the right default per the HAIP
|
|
33
|
+
* convention. Callers can override via `SignAuthorizationRequestOptions.aud`
|
|
34
|
+
* when targeting wallets that announce themselves via `wallet_metadata`. */
|
|
35
|
+
export declare const DEFAULT_JAR_AUDIENCE = "https://self-issued.me/v2";
|
|
36
|
+
/** Default JAR lifetime — 5 minutes. RFC 9101 §4 doesn't fix a value but
|
|
37
|
+
* recommends a "short" lifetime; HAIP doesn't pin one either. 5 min
|
|
38
|
+
* matches OID4VCI's c_nonce window for symmetry across endpoints, and is
|
|
39
|
+
* the audit-recommended default (EUDI compliance audit, 2026-05). */
|
|
40
|
+
export declare const DEFAULT_JAR_LIFETIME_SECONDS: number;
|
|
22
41
|
export interface SignAuthorizationRequestOptions {
|
|
23
42
|
/** The verifier's Authorization Request to sign. Must already include
|
|
24
43
|
* the verifier-side fields (`client_id`, `nonce`, `response_uri`, etc).
|
|
@@ -27,6 +46,20 @@ export interface SignAuthorizationRequestOptions {
|
|
|
27
46
|
/** The verifier's signing material — produced by `generateSigningCert`
|
|
28
47
|
* or supplied externally. */
|
|
29
48
|
readonly cert: SigningCert;
|
|
49
|
+
/** Audience for the signed JAR. Defaults to {@link DEFAULT_JAR_AUDIENCE}
|
|
50
|
+
* (`https://self-issued.me/v2`) per HAIP convention (RFC 9101 §2.1 +
|
|
51
|
+
* OID4VP §5.8). Pass `undefined` explicitly to fall through to the
|
|
52
|
+
* default — a JAR is never emitted without an `aud` claim. */
|
|
53
|
+
readonly aud?: string;
|
|
54
|
+
/** JAR lifetime in seconds. `iat = now`, `exp = now + lifetime`.
|
|
55
|
+
* Defaults to {@link DEFAULT_JAR_LIFETIME_SECONDS} (300 = 5 min).
|
|
56
|
+
* (OID4VP §5.8 + RFC 9101 §4) */
|
|
57
|
+
readonly jarLifetimeSeconds?: number;
|
|
58
|
+
/** Override `iat` source — useful for deterministic tests. Defaults
|
|
59
|
+
* to `() => Math.floor(Date.now() / 1000)`. Returned value is treated
|
|
60
|
+
* as the unix-seconds timestamp written to `iat`; `exp` is
|
|
61
|
+
* `now() + jarLifetimeSeconds`. */
|
|
62
|
+
readonly now?: () => number;
|
|
30
63
|
}
|
|
31
64
|
/**
|
|
32
65
|
* Sign an OID4VP Authorization Request as a compact-serialised JWS,
|
|
@@ -40,8 +73,15 @@ export interface SignAuthorizationRequestOptions {
|
|
|
40
73
|
* separate key-discovery step
|
|
41
74
|
*
|
|
42
75
|
* The JWS payload IS the request object — claims at the top level, not
|
|
43
|
-
* wrapped in some envelope (RFC 9101 §10.2).
|
|
44
|
-
*
|
|
76
|
+
* wrapped in some envelope (RFC 9101 §10.2). On top of the request
|
|
77
|
+
* claims the signer always overlays:
|
|
78
|
+
* - `aud` — defaults to `https://self-issued.me/v2`
|
|
79
|
+
* - `iat` — set to `now()` (unix seconds)
|
|
80
|
+
* - `exp` — set to `iat + jarLifetimeSeconds` (default 300 s)
|
|
81
|
+
*
|
|
82
|
+
* If the request payload already carries any of `aud`/`iat`/`exp`, those
|
|
83
|
+
* payload-level values win — the signer is non-destructive. Caller
|
|
84
|
+
* serves the result with content type `application/oauth-authz-req+jwt`.
|
|
45
85
|
*
|
|
46
86
|
* @throws {@link Oid4vpError} with `oid4vp.jar_signing_failed` if the
|
|
47
87
|
* private key is malformed or signing fails.
|
package/dist/jar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jar.d.ts","sourceRoot":"","sources":["../src/jar.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"jar.d.ts","sourceRoot":"","sources":["../src/jar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB;;;;;4EAK4E;AAC5E,eAAO,MAAM,oBAAoB,8BAA8B,CAAC;AAEhE;;;qEAGqE;AACrE,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAEnD,MAAM,WAAW,+BAA+B;IAC9C;;2EAEuE;IACvE,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC;iCAC6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;;kEAG8D;IAC9D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;qCAEiC;IACjC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC;;;uCAGmC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,MAAM,CAAC,CAwEjB"}
|
package/dist/jar.js
CHANGED
|
@@ -17,9 +17,28 @@
|
|
|
17
17
|
* For the EUDIW HAIP profile + the EU reference wallet's demo build,
|
|
18
18
|
* `x509_san_dns` (with this signed JAR shape) is the only `client_id_prefix`
|
|
19
19
|
* the wallet accepts. Production verifiers MUST sign their requests.
|
|
20
|
+
*
|
|
21
|
+
* In addition to the OID4VP request claims, the signer always emits the
|
|
22
|
+
* standard JWT claims `aud`, `iat`, `exp` on the JAR payload (RFC 9101
|
|
23
|
+
* §4 recommends them; OID4VP §5.8 mandates `aud`; HAIP-strict wallets
|
|
24
|
+
* reject when any of the three is absent). The audience defaults to the
|
|
25
|
+
* static pseudo-issuer `https://self-issued.me/v2` and the lifetime
|
|
26
|
+
* defaults to 5 minutes — both are configurable per call.
|
|
20
27
|
*/
|
|
21
28
|
import { SignJWT, importPKCS8 } from "jose";
|
|
22
29
|
import { Oid4vpError, } from "./types.js";
|
|
30
|
+
/** OID4VP §5.8 — default `aud` for the signed JAR. Wallets check `aud`
|
|
31
|
+
* against either their own issuer URL (dynamic discovery) or the static
|
|
32
|
+
* pseudo-issuer `https://self-issued.me/v2`. We don't do dynamic wallet
|
|
33
|
+
* discovery — so the static value is the right default per the HAIP
|
|
34
|
+
* convention. Callers can override via `SignAuthorizationRequestOptions.aud`
|
|
35
|
+
* when targeting wallets that announce themselves via `wallet_metadata`. */
|
|
36
|
+
export const DEFAULT_JAR_AUDIENCE = "https://self-issued.me/v2";
|
|
37
|
+
/** Default JAR lifetime — 5 minutes. RFC 9101 §4 doesn't fix a value but
|
|
38
|
+
* recommends a "short" lifetime; HAIP doesn't pin one either. 5 min
|
|
39
|
+
* matches OID4VCI's c_nonce window for symmetry across endpoints, and is
|
|
40
|
+
* the audit-recommended default (EUDI compliance audit, 2026-05). */
|
|
41
|
+
export const DEFAULT_JAR_LIFETIME_SECONDS = 5 * 60;
|
|
23
42
|
/**
|
|
24
43
|
* Sign an OID4VP Authorization Request as a compact-serialised JWS,
|
|
25
44
|
* formatted per RFC 9101 + OID4VP §5.10.
|
|
@@ -32,8 +51,15 @@ import { Oid4vpError, } from "./types.js";
|
|
|
32
51
|
* separate key-discovery step
|
|
33
52
|
*
|
|
34
53
|
* The JWS payload IS the request object — claims at the top level, not
|
|
35
|
-
* wrapped in some envelope (RFC 9101 §10.2).
|
|
36
|
-
*
|
|
54
|
+
* wrapped in some envelope (RFC 9101 §10.2). On top of the request
|
|
55
|
+
* claims the signer always overlays:
|
|
56
|
+
* - `aud` — defaults to `https://self-issued.me/v2`
|
|
57
|
+
* - `iat` — set to `now()` (unix seconds)
|
|
58
|
+
* - `exp` — set to `iat + jarLifetimeSeconds` (default 300 s)
|
|
59
|
+
*
|
|
60
|
+
* If the request payload already carries any of `aud`/`iat`/`exp`, those
|
|
61
|
+
* payload-level values win — the signer is non-destructive. Caller
|
|
62
|
+
* serves the result with content type `application/oauth-authz-req+jwt`.
|
|
37
63
|
*
|
|
38
64
|
* @throws {@link Oid4vpError} with `oid4vp.jar_signing_failed` if the
|
|
39
65
|
* private key is malformed or signing fails.
|
|
@@ -54,13 +80,32 @@ export async function signAuthorizationRequest(options) {
|
|
|
54
80
|
catch (err) {
|
|
55
81
|
throw new Oid4vpError("oid4vp.jar_signing_failed", `signAuthorizationRequest: failed to import private key: ${err instanceof Error ? err.message : String(err)}`);
|
|
56
82
|
}
|
|
83
|
+
// Resolve the JWT timing claims. `options.aud === undefined` falls
|
|
84
|
+
// through to the default (per the option's contract) — callers cannot
|
|
85
|
+
// suppress the claim, only override its value.
|
|
86
|
+
const aud = options.aud ?? DEFAULT_JAR_AUDIENCE;
|
|
87
|
+
const lifetime = options.jarLifetimeSeconds ?? DEFAULT_JAR_LIFETIME_SECONDS;
|
|
88
|
+
const nowFn = options.now ?? (() => Math.floor(Date.now() / 1000));
|
|
89
|
+
const iat = nowFn();
|
|
90
|
+
const exp = iat + lifetime;
|
|
57
91
|
try {
|
|
58
92
|
// Spread into a fresh mutable object — `jose.SignJWT` wants
|
|
59
93
|
// `JWTPayload` (mutable, index-signature) while `AuthorizationRequest`
|
|
60
94
|
// is strict-readonly. The spread copies own enumerable props and
|
|
61
95
|
// produces a value of structurally-compatible type without an
|
|
62
96
|
// `as unknown as` double-cast.
|
|
97
|
+
//
|
|
98
|
+
// The OID4VP request fields go in first; if the caller has already
|
|
99
|
+
// set `aud`/`iat`/`exp` at the request level (unusual but legal),
|
|
100
|
+
// those payload-level values win. Otherwise we apply the resolved
|
|
101
|
+
// defaults below. Either way the JAR carries all three claims.
|
|
63
102
|
const payload = { ...options.request };
|
|
103
|
+
if (payload["aud"] === undefined)
|
|
104
|
+
payload["aud"] = aud;
|
|
105
|
+
if (payload["iat"] === undefined)
|
|
106
|
+
payload["iat"] = iat;
|
|
107
|
+
if (payload["exp"] === undefined)
|
|
108
|
+
payload["exp"] = exp;
|
|
64
109
|
const jwt = await new SignJWT(payload)
|
|
65
110
|
.setProtectedHeader({
|
|
66
111
|
alg: "ES256",
|
package/dist/jar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jar.js","sourceRoot":"","sources":["../src/jar.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"jar.js","sourceRoot":"","sources":["../src/jar.ts"],"names":[],"mappings":"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"}
|
package/dist/random.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic randomness helpers for OID4VP authorization requests.
|
|
3
|
+
*
|
|
4
|
+
* Per OID4VP Final 1.0 §5.3 + §11.2 — verifier-supplied opaque values
|
|
5
|
+
* (`state`, `nonce`) MUST carry at least 128 bits of entropy. Even when
|
|
6
|
+
* holder binding (KB-JWT) is present, these fields are reused for CSRF
|
|
7
|
+
* stitching, replay protection and small values invite brute force in
|
|
8
|
+
* edge cases where the value leaks externally (e.g. via referer headers
|
|
9
|
+
* in poorly-implemented universal-link handling).
|
|
10
|
+
*
|
|
11
|
+
* Both helpers draw 16 random bytes (128 bits) from `node:crypto` and
|
|
12
|
+
* encode them in the form the spec prefers for that field:
|
|
13
|
+
*
|
|
14
|
+
* - `state` → hex (RFC 6648 implementation hint, also what the EU
|
|
15
|
+
* reference wallet's emulator build sends back verbatim — using hex
|
|
16
|
+
* keeps the value safe across URL-encoded transports).
|
|
17
|
+
* - `nonce` → base64url no-pad (matches what the wallet's KB-JWT
|
|
18
|
+
* `nonce` claim will echo, per OID4VP §5.5 + SD-JWT VC §4.3).
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* 128-bit random `state` value, hex-encoded.
|
|
22
|
+
*
|
|
23
|
+
* `state` is the verifier-controlled correlation token the wallet
|
|
24
|
+
* echoes back unchanged in the Authorization Response. Verifiers MUST
|
|
25
|
+
* generate this with enough entropy that a third party cannot guess a
|
|
26
|
+
* pending session id (OID4VP §5.3 + §11.2).
|
|
27
|
+
*
|
|
28
|
+
* 16 bytes → 128 bits → 32 hex chars. Use `generateNonce` for the
|
|
29
|
+
* cryptographic challenge in the same request — they serve different
|
|
30
|
+
* purposes and MUST NOT be reused for one another.
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateState(): string;
|
|
33
|
+
/**
|
|
34
|
+
* 128-bit random `nonce` value, base64url-encoded (no padding).
|
|
35
|
+
*
|
|
36
|
+
* `nonce` is the cryptographic challenge the wallet binds into its
|
|
37
|
+
* KB-JWT to prove possession of the holder key. It MUST be unique per
|
|
38
|
+
* request and at least 128 bits (OID4VP §5.3 + §11.2). 16 bytes →
|
|
39
|
+
* 128 bits → 22 base64url chars (no padding).
|
|
40
|
+
*
|
|
41
|
+
* Use `generateState` for the verifier's correlation token in the same
|
|
42
|
+
* request — they serve different purposes and MUST NOT be reused.
|
|
43
|
+
*/
|
|
44
|
+
export declare function generateNonce(): string;
|
|
45
|
+
//# sourceMappingURL=random.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
package/dist/random.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptographic randomness helpers for OID4VP authorization requests.
|
|
3
|
+
*
|
|
4
|
+
* Per OID4VP Final 1.0 §5.3 + §11.2 — verifier-supplied opaque values
|
|
5
|
+
* (`state`, `nonce`) MUST carry at least 128 bits of entropy. Even when
|
|
6
|
+
* holder binding (KB-JWT) is present, these fields are reused for CSRF
|
|
7
|
+
* stitching, replay protection and small values invite brute force in
|
|
8
|
+
* edge cases where the value leaks externally (e.g. via referer headers
|
|
9
|
+
* in poorly-implemented universal-link handling).
|
|
10
|
+
*
|
|
11
|
+
* Both helpers draw 16 random bytes (128 bits) from `node:crypto` and
|
|
12
|
+
* encode them in the form the spec prefers for that field:
|
|
13
|
+
*
|
|
14
|
+
* - `state` → hex (RFC 6648 implementation hint, also what the EU
|
|
15
|
+
* reference wallet's emulator build sends back verbatim — using hex
|
|
16
|
+
* keeps the value safe across URL-encoded transports).
|
|
17
|
+
* - `nonce` → base64url no-pad (matches what the wallet's KB-JWT
|
|
18
|
+
* `nonce` claim will echo, per OID4VP §5.5 + SD-JWT VC §4.3).
|
|
19
|
+
*/
|
|
20
|
+
import { randomBytes } from "node:crypto";
|
|
21
|
+
/**
|
|
22
|
+
* 128-bit random `state` value, hex-encoded.
|
|
23
|
+
*
|
|
24
|
+
* `state` is the verifier-controlled correlation token the wallet
|
|
25
|
+
* echoes back unchanged in the Authorization Response. Verifiers MUST
|
|
26
|
+
* generate this with enough entropy that a third party cannot guess a
|
|
27
|
+
* pending session id (OID4VP §5.3 + §11.2).
|
|
28
|
+
*
|
|
29
|
+
* 16 bytes → 128 bits → 32 hex chars. Use `generateNonce` for the
|
|
30
|
+
* cryptographic challenge in the same request — they serve different
|
|
31
|
+
* purposes and MUST NOT be reused for one another.
|
|
32
|
+
*/
|
|
33
|
+
export function generateState() {
|
|
34
|
+
return randomBytes(16).toString("hex");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 128-bit random `nonce` value, base64url-encoded (no padding).
|
|
38
|
+
*
|
|
39
|
+
* `nonce` is the cryptographic challenge the wallet binds into its
|
|
40
|
+
* KB-JWT to prove possession of the holder key. It MUST be unique per
|
|
41
|
+
* request and at least 128 bits (OID4VP §5.3 + §11.2). 16 bytes →
|
|
42
|
+
* 128 bits → 22 base64url chars (no padding).
|
|
43
|
+
*
|
|
44
|
+
* Use `generateState` for the verifier's correlation token in the same
|
|
45
|
+
* request — they serve different purposes and MUST NOT be reused.
|
|
46
|
+
*/
|
|
47
|
+
export function generateNonce() {
|
|
48
|
+
return randomBytes(16).toString("base64url");
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=random.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"random.js","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `direct_post.jwt` response mode — OID4VP Final 1.0 §8.3.1, HAIP §5.1.
|
|
3
|
+
*
|
|
4
|
+
* Where `direct_post` sends the Authorization Response as plaintext
|
|
5
|
+
* `application/x-www-form-urlencoded`, `direct_post.jwt` wraps the
|
|
6
|
+
* exact same fields (`vp_token`, optional `presentation_submission`,
|
|
7
|
+
* `state`, `iss`) into a JSON object, then encrypts that object into
|
|
8
|
+
* a compact-serialised JWE keyed by the verifier's published
|
|
9
|
+
* encryption JWK. The JWE rides on a single form field named
|
|
10
|
+
* `response`.
|
|
11
|
+
*
|
|
12
|
+
* wallet ─ JSON encode vp_token + state + iss ──►
|
|
13
|
+
* ─ JWE-wrap with verifier.client_metadata.jwks[*].use="enc" ──►
|
|
14
|
+
* ─ form-encode as response=<JWE> ──►
|
|
15
|
+
* verifier
|
|
16
|
+
*
|
|
17
|
+
* verifier ─ extract `response` form param ──►
|
|
18
|
+
* ─ decrypt JWE with private encryption key ──►
|
|
19
|
+
* ─ JSON parse the cleartext payload ──►
|
|
20
|
+
* ─ feed into parseAuthorizationResponseBody equivalent ──►
|
|
21
|
+
*
|
|
22
|
+
* Why HAIP mandates this: with plaintext `direct_post` the PID claims
|
|
23
|
+
* (disclosed names, birthdates, addresses) travel as form fields the
|
|
24
|
+
* verifier's TLS terminator, reverse proxy, and downstream log
|
|
25
|
+
* pipelines can capture. Encrypting end-to-end (wallet → application)
|
|
26
|
+
* shrinks the trust boundary to the application that holds the
|
|
27
|
+
* private key.
|
|
28
|
+
*
|
|
29
|
+
* The crypto primitives used by default:
|
|
30
|
+
* - `alg = ECDH-ES` — direct ECDH-derived CEK, no extra key wrap.
|
|
31
|
+
* P-256 is the curve every HAIP wallet implements.
|
|
32
|
+
* - `enc = A256GCM` — authenticated encryption of the payload.
|
|
33
|
+
*
|
|
34
|
+
* Callers can opt into different `alg`/`enc` values via the options.
|
|
35
|
+
*/
|
|
36
|
+
import type { JsonWebKey } from "@gramota/jose";
|
|
37
|
+
import { type AuthorizationResponse } from "./types.js";
|
|
38
|
+
/** Default JWE key-agreement algorithm — ECDH-ES, the option the EU
|
|
39
|
+
* reference wallet and HAIP §5.1 baseline implement. */
|
|
40
|
+
export declare const DEFAULT_RESPONSE_JWE_ALG = "ECDH-ES";
|
|
41
|
+
/** Default JWE content-encryption algorithm — A256GCM (authenticated). */
|
|
42
|
+
export declare const DEFAULT_RESPONSE_JWE_ENC = "A256GCM";
|
|
43
|
+
/**
|
|
44
|
+
* Generate a fresh JWE encryption keypair for the verifier.
|
|
45
|
+
*
|
|
46
|
+
* The public JWK goes into `client_metadata.jwks.keys[]` on the
|
|
47
|
+
* Authorization Request; the private JWK stays on the verifier and
|
|
48
|
+
* decrypts inbound `direct_post.jwt` responses.
|
|
49
|
+
*
|
|
50
|
+
* Returns both JWKs annotated with:
|
|
51
|
+
* - `use: "enc"` (RFC 7517 §4.2) so wallets can pick the right key
|
|
52
|
+
* when both signing and encryption keys are published
|
|
53
|
+
* - `alg`: the key-agreement algorithm (default ECDH-ES)
|
|
54
|
+
* - `kid` (optional, caller-supplied)
|
|
55
|
+
*
|
|
56
|
+
* Production deployments may want HSM-backed keys instead — the
|
|
57
|
+
* encryption keypair is a long-lived secret per verifier, not a
|
|
58
|
+
* per-request ephemeral. This generator is the development /
|
|
59
|
+
* pinned-trust path; the surface contract (JsonWebKey in and out) is
|
|
60
|
+
* the same regardless of where the bits come from.
|
|
61
|
+
*/
|
|
62
|
+
export interface GenerateResponseEncryptionKeyOptions {
|
|
63
|
+
/** Key-agreement algorithm. Default `"ECDH-ES"`. */
|
|
64
|
+
readonly alg?: string;
|
|
65
|
+
/** Optional key id — written to both JWKs as `kid`. */
|
|
66
|
+
readonly kid?: string;
|
|
67
|
+
}
|
|
68
|
+
export declare function generateResponseEncryptionKey(options?: GenerateResponseEncryptionKeyOptions): Promise<{
|
|
69
|
+
publicJwk: JsonWebKey;
|
|
70
|
+
privateJwk: JsonWebKey;
|
|
71
|
+
}>;
|
|
72
|
+
export interface EncryptAuthorizationResponseOptions {
|
|
73
|
+
/** The Authorization Response to wrap. The same object you'd hand to
|
|
74
|
+
* `buildAuthorizationResponseBody` for `direct_post`. */
|
|
75
|
+
readonly response: AuthorizationResponse;
|
|
76
|
+
/** Verifier's encryption JWK — picked from `client_metadata.jwks`. */
|
|
77
|
+
readonly encryptionKey: JsonWebKey;
|
|
78
|
+
/** Optional override of the JWE `alg` header. Default
|
|
79
|
+
* {@link DEFAULT_RESPONSE_JWE_ALG} or `encryptionKey.alg` when set. */
|
|
80
|
+
readonly alg?: string;
|
|
81
|
+
/** Optional override of the JWE `enc` header. Default
|
|
82
|
+
* {@link DEFAULT_RESPONSE_JWE_ENC}. */
|
|
83
|
+
readonly enc?: string;
|
|
84
|
+
/** Optional override of the JWE `kid` header. Default
|
|
85
|
+
* `encryptionKey.kid`. */
|
|
86
|
+
readonly kid?: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Encrypt an Authorization Response per OID4VP §8.3.1.
|
|
90
|
+
*
|
|
91
|
+
* The cleartext is the JSON object the spec describes — same shape as
|
|
92
|
+
* the form-encoded `direct_post` body would carry, but as JSON rather
|
|
93
|
+
* than URL-encoded form. The output is a compact-serialised JWE
|
|
94
|
+
* suitable for the `response` form parameter of the wallet's POST to
|
|
95
|
+
* the verifier's `response_uri`.
|
|
96
|
+
*
|
|
97
|
+
* @throws {@link Oid4vpError} `oid4vp.response_encryption_failed`.
|
|
98
|
+
*/
|
|
99
|
+
export declare function encryptAuthorizationResponse(options: EncryptAuthorizationResponseOptions): Promise<string>;
|
|
100
|
+
export interface DecryptAuthorizationResponseOptions {
|
|
101
|
+
/** The compact-serialised JWE pulled from the `response` form field. */
|
|
102
|
+
readonly jwe: string;
|
|
103
|
+
/** The verifier's private encryption JWK — counterpart to the public
|
|
104
|
+
* key published in `client_metadata.jwks`. */
|
|
105
|
+
readonly privateKey: JsonWebKey;
|
|
106
|
+
/** Optional allowlist of acceptable `enc` values. Default
|
|
107
|
+
* `["A256GCM"]` — narrow / widen for interop. */
|
|
108
|
+
readonly enc?: readonly string[];
|
|
109
|
+
/** Optional allowlist of acceptable `alg` values. Default
|
|
110
|
+
* `["ECDH-ES"]`. */
|
|
111
|
+
readonly alg?: readonly string[];
|
|
112
|
+
}
|
|
113
|
+
export interface DecryptedAuthorizationResponse {
|
|
114
|
+
/** The wallet's Authorization Response, ready to feed to the
|
|
115
|
+
* verifier's existing validation pipeline. */
|
|
116
|
+
readonly response: AuthorizationResponse;
|
|
117
|
+
/** The verified JWE protected header — `alg`, `enc`, `kid`. */
|
|
118
|
+
readonly header: Readonly<Record<string, unknown>>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Decrypt a `direct_post.jwt` Authorization Response.
|
|
122
|
+
*
|
|
123
|
+
* Reverses {@link encryptAuthorizationResponse}: imports the private
|
|
124
|
+
* JWK, runs JWE compact-decrypt, JSON-parses the cleartext, validates
|
|
125
|
+
* shape (vp_token present, PEX path carries presentation_submission),
|
|
126
|
+
* and returns the {@link AuthorizationResponse}.
|
|
127
|
+
*
|
|
128
|
+
* The function enforces:
|
|
129
|
+
* - The JWE protected header `alg` is in the caller's allowlist
|
|
130
|
+
* (default `["ECDH-ES"]`).
|
|
131
|
+
* - The JWE protected header `enc` is in the caller's allowlist
|
|
132
|
+
* (default `["A256GCM"]`).
|
|
133
|
+
* - The cleartext is a JSON object (not an array, not bare string).
|
|
134
|
+
* - `vp_token` is present and is one of: string, string[], DCQL
|
|
135
|
+
* credential map.
|
|
136
|
+
* - PEX responses (string / string[]) carry `presentation_submission`;
|
|
137
|
+
* DCQL responses (object) need not.
|
|
138
|
+
*
|
|
139
|
+
* @throws {@link Oid4vpError} with codes
|
|
140
|
+
* `oid4vp.response_encryption_failed` (decryption / header rejection),
|
|
141
|
+
* `oid4vp.required_field_missing`, `oid4vp.invalid_value_type`,
|
|
142
|
+
* `oid4vp.malformed_body`, or `oid4vp.invalid_json`.
|
|
143
|
+
*/
|
|
144
|
+
export declare function decryptAuthorizationResponse(options: DecryptAuthorizationResponseOptions): Promise<DecryptedAuthorizationResponse>;
|
|
145
|
+
//# sourceMappingURL=response-jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-jwt.d.ts","sourceRoot":"","sources":["../src/response-jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAe,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAErE;wDACwD;AACxD,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAClD,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAElD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,oCAAoC;IACnD,oDAAoD;IACpD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,6BAA6B,CACjD,OAAO,GAAE,oCAAyC,GACjD,OAAO,CAAC;IAAE,SAAS,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,CAwB5D;AAMD,MAAM,WAAW,mCAAmC;IAClD;6DACyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IACzC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;IACnC;2EACuE;IACvE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;2CACuC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;8BAC0B;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,mCAAmC,GAC3C,OAAO,CAAC,MAAM,CAAC,CA2DjB;AA2BD,MAAM,WAAW,mCAAmC;IAClD,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;kDAC8C;IAC9C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC;qDACiD;IACjD,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;wBACoB;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,8BAA8B;IAC7C;kDAC8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IACzC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACpD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,mCAAmC,GAC3C,OAAO,CAAC,8BAA8B,CAAC,CA0HzC"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `direct_post.jwt` response mode — OID4VP Final 1.0 §8.3.1, HAIP §5.1.
|
|
3
|
+
*
|
|
4
|
+
* Where `direct_post` sends the Authorization Response as plaintext
|
|
5
|
+
* `application/x-www-form-urlencoded`, `direct_post.jwt` wraps the
|
|
6
|
+
* exact same fields (`vp_token`, optional `presentation_submission`,
|
|
7
|
+
* `state`, `iss`) into a JSON object, then encrypts that object into
|
|
8
|
+
* a compact-serialised JWE keyed by the verifier's published
|
|
9
|
+
* encryption JWK. The JWE rides on a single form field named
|
|
10
|
+
* `response`.
|
|
11
|
+
*
|
|
12
|
+
* wallet ─ JSON encode vp_token + state + iss ──►
|
|
13
|
+
* ─ JWE-wrap with verifier.client_metadata.jwks[*].use="enc" ──►
|
|
14
|
+
* ─ form-encode as response=<JWE> ──►
|
|
15
|
+
* verifier
|
|
16
|
+
*
|
|
17
|
+
* verifier ─ extract `response` form param ──►
|
|
18
|
+
* ─ decrypt JWE with private encryption key ──►
|
|
19
|
+
* ─ JSON parse the cleartext payload ──►
|
|
20
|
+
* ─ feed into parseAuthorizationResponseBody equivalent ──►
|
|
21
|
+
*
|
|
22
|
+
* Why HAIP mandates this: with plaintext `direct_post` the PID claims
|
|
23
|
+
* (disclosed names, birthdates, addresses) travel as form fields the
|
|
24
|
+
* verifier's TLS terminator, reverse proxy, and downstream log
|
|
25
|
+
* pipelines can capture. Encrypting end-to-end (wallet → application)
|
|
26
|
+
* shrinks the trust boundary to the application that holds the
|
|
27
|
+
* private key.
|
|
28
|
+
*
|
|
29
|
+
* The crypto primitives used by default:
|
|
30
|
+
* - `alg = ECDH-ES` — direct ECDH-derived CEK, no extra key wrap.
|
|
31
|
+
* P-256 is the curve every HAIP wallet implements.
|
|
32
|
+
* - `enc = A256GCM` — authenticated encryption of the payload.
|
|
33
|
+
*
|
|
34
|
+
* Callers can opt into different `alg`/`enc` values via the options.
|
|
35
|
+
*/
|
|
36
|
+
import { CompactEncrypt, compactDecrypt, exportJWK, generateKeyPair, importJWK } from "jose";
|
|
37
|
+
import { Oid4vpError } from "./types.js";
|
|
38
|
+
/** Default JWE key-agreement algorithm — ECDH-ES, the option the EU
|
|
39
|
+
* reference wallet and HAIP §5.1 baseline implement. */
|
|
40
|
+
export const DEFAULT_RESPONSE_JWE_ALG = "ECDH-ES";
|
|
41
|
+
/** Default JWE content-encryption algorithm — A256GCM (authenticated). */
|
|
42
|
+
export const DEFAULT_RESPONSE_JWE_ENC = "A256GCM";
|
|
43
|
+
export async function generateResponseEncryptionKey(options = {}) {
|
|
44
|
+
const alg = options.alg ?? DEFAULT_RESPONSE_JWE_ALG;
|
|
45
|
+
let keys;
|
|
46
|
+
try {
|
|
47
|
+
keys = await generateKeyPair(alg, { extractable: true });
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
throw new Oid4vpError("oid4vp.cert_generation_failed", `generateResponseEncryptionKey: alg ${JSON.stringify(alg)} not supported: ${err instanceof Error ? err.message : String(err)}`);
|
|
51
|
+
}
|
|
52
|
+
const publicJwk = (await exportJWK(keys.publicKey));
|
|
53
|
+
const privateJwk = (await exportJWK(keys.privateKey));
|
|
54
|
+
publicJwk.use = "enc";
|
|
55
|
+
privateJwk.use = "enc";
|
|
56
|
+
publicJwk.alg = alg;
|
|
57
|
+
privateJwk.alg = alg;
|
|
58
|
+
if (options.kid !== undefined) {
|
|
59
|
+
publicJwk.kid = options.kid;
|
|
60
|
+
privateJwk.kid = options.kid;
|
|
61
|
+
}
|
|
62
|
+
return { publicJwk, privateJwk };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Encrypt an Authorization Response per OID4VP §8.3.1.
|
|
66
|
+
*
|
|
67
|
+
* The cleartext is the JSON object the spec describes — same shape as
|
|
68
|
+
* the form-encoded `direct_post` body would carry, but as JSON rather
|
|
69
|
+
* than URL-encoded form. The output is a compact-serialised JWE
|
|
70
|
+
* suitable for the `response` form parameter of the wallet's POST to
|
|
71
|
+
* the verifier's `response_uri`.
|
|
72
|
+
*
|
|
73
|
+
* @throws {@link Oid4vpError} `oid4vp.response_encryption_failed`.
|
|
74
|
+
*/
|
|
75
|
+
export async function encryptAuthorizationResponse(options) {
|
|
76
|
+
if (options.encryptionKey === null ||
|
|
77
|
+
typeof options.encryptionKey !== "object") {
|
|
78
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", "encryptAuthorizationResponse: encryptionKey is required");
|
|
79
|
+
}
|
|
80
|
+
const alg = options.alg ??
|
|
81
|
+
(typeof options.encryptionKey.alg === "string"
|
|
82
|
+
? options.encryptionKey.alg
|
|
83
|
+
: DEFAULT_RESPONSE_JWE_ALG);
|
|
84
|
+
const enc = options.enc ?? DEFAULT_RESPONSE_JWE_ENC;
|
|
85
|
+
const payload = buildJwtResponsePayload(options.response);
|
|
86
|
+
let publicKey;
|
|
87
|
+
try {
|
|
88
|
+
publicKey = await importJWK(options.encryptionKey, alg);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", `encryptAuthorizationResponse: failed to import encryption JWK: ${err instanceof Error ? err.message : String(err)}`);
|
|
92
|
+
}
|
|
93
|
+
const protectedHeader = { alg, enc };
|
|
94
|
+
const kid = options.kid ??
|
|
95
|
+
(typeof options.encryptionKey.kid === "string"
|
|
96
|
+
? options.encryptionKey.kid
|
|
97
|
+
: undefined);
|
|
98
|
+
if (kid !== undefined)
|
|
99
|
+
protectedHeader["kid"] = kid;
|
|
100
|
+
try {
|
|
101
|
+
const cleartext = new TextEncoder().encode(JSON.stringify(payload));
|
|
102
|
+
return await new CompactEncrypt(cleartext)
|
|
103
|
+
.setProtectedHeader(protectedHeader)
|
|
104
|
+
.encrypt(publicKey);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", `encryptAuthorizationResponse: JWE encryption failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Convert an AuthorizationResponse to the JSON object that
|
|
111
|
+
* `direct_post.jwt` ships as the JWE cleartext.
|
|
112
|
+
*
|
|
113
|
+
* The JWE cleartext is conceptually the same as the `direct_post`
|
|
114
|
+
* form body, except parameters are JSON-typed (no URL encoding /
|
|
115
|
+
* string coercion), and complex values (vp_token map, submission
|
|
116
|
+
* map) are nested as objects rather than embedded as JSON-string
|
|
117
|
+
* fields. This mirrors what production EU wallets send.
|
|
118
|
+
*/
|
|
119
|
+
function buildJwtResponsePayload(response) {
|
|
120
|
+
const out = { vp_token: response.vp_token };
|
|
121
|
+
if (response.presentation_submission !== undefined) {
|
|
122
|
+
out["presentation_submission"] = response.presentation_submission;
|
|
123
|
+
}
|
|
124
|
+
if (response.state !== undefined)
|
|
125
|
+
out["state"] = response.state;
|
|
126
|
+
if (response.iss !== undefined)
|
|
127
|
+
out["iss"] = response.iss;
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Decrypt a `direct_post.jwt` Authorization Response.
|
|
132
|
+
*
|
|
133
|
+
* Reverses {@link encryptAuthorizationResponse}: imports the private
|
|
134
|
+
* JWK, runs JWE compact-decrypt, JSON-parses the cleartext, validates
|
|
135
|
+
* shape (vp_token present, PEX path carries presentation_submission),
|
|
136
|
+
* and returns the {@link AuthorizationResponse}.
|
|
137
|
+
*
|
|
138
|
+
* The function enforces:
|
|
139
|
+
* - The JWE protected header `alg` is in the caller's allowlist
|
|
140
|
+
* (default `["ECDH-ES"]`).
|
|
141
|
+
* - The JWE protected header `enc` is in the caller's allowlist
|
|
142
|
+
* (default `["A256GCM"]`).
|
|
143
|
+
* - The cleartext is a JSON object (not an array, not bare string).
|
|
144
|
+
* - `vp_token` is present and is one of: string, string[], DCQL
|
|
145
|
+
* credential map.
|
|
146
|
+
* - PEX responses (string / string[]) carry `presentation_submission`;
|
|
147
|
+
* DCQL responses (object) need not.
|
|
148
|
+
*
|
|
149
|
+
* @throws {@link Oid4vpError} with codes
|
|
150
|
+
* `oid4vp.response_encryption_failed` (decryption / header rejection),
|
|
151
|
+
* `oid4vp.required_field_missing`, `oid4vp.invalid_value_type`,
|
|
152
|
+
* `oid4vp.malformed_body`, or `oid4vp.invalid_json`.
|
|
153
|
+
*/
|
|
154
|
+
export async function decryptAuthorizationResponse(options) {
|
|
155
|
+
if (typeof options.jwe !== "string" || options.jwe.length === 0) {
|
|
156
|
+
throw new Oid4vpError("oid4vp.required_field_missing", "decryptAuthorizationResponse: jwe is required");
|
|
157
|
+
}
|
|
158
|
+
if (options.privateKey === null ||
|
|
159
|
+
typeof options.privateKey !== "object") {
|
|
160
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", "decryptAuthorizationResponse: privateKey is required");
|
|
161
|
+
}
|
|
162
|
+
const allowedAlgs = options.alg ?? [DEFAULT_RESPONSE_JWE_ALG];
|
|
163
|
+
const allowedEncs = options.enc ?? [DEFAULT_RESPONSE_JWE_ENC];
|
|
164
|
+
// Pre-flight header inspection — the JWE library will also reject
|
|
165
|
+
// out-of-allowlist algs once we pass keyManagementAlgorithms /
|
|
166
|
+
// contentEncryptionAlgorithms, but we want spec-quality errors with
|
|
167
|
+
// our stable codes, so we look at the header explicitly first.
|
|
168
|
+
const segments = options.jwe.split(".");
|
|
169
|
+
if (segments.length !== 5) {
|
|
170
|
+
throw new Oid4vpError("oid4vp.malformed_body", "decryptAuthorizationResponse: malformed JWE (compact serialisation has 5 segments)");
|
|
171
|
+
}
|
|
172
|
+
let header;
|
|
173
|
+
try {
|
|
174
|
+
const json = Buffer.from(segments[0], "base64url").toString("utf-8");
|
|
175
|
+
const parsed = JSON.parse(json);
|
|
176
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
177
|
+
throw new Error("JWE header is not a JSON object");
|
|
178
|
+
}
|
|
179
|
+
header = parsed;
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
throw new Oid4vpError("oid4vp.malformed_body", `decryptAuthorizationResponse: malformed JWE header: ${err instanceof Error ? err.message : String(err)}`);
|
|
183
|
+
}
|
|
184
|
+
const headerAlg = header["alg"];
|
|
185
|
+
const headerEnc = header["enc"];
|
|
186
|
+
if (typeof headerAlg !== "string" ||
|
|
187
|
+
!allowedAlgs.includes(headerAlg)) {
|
|
188
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", `decryptAuthorizationResponse: JWE alg ${JSON.stringify(headerAlg)} is not in allowlist (${allowedAlgs.join(", ")})`);
|
|
189
|
+
}
|
|
190
|
+
if (typeof headerEnc !== "string" ||
|
|
191
|
+
!allowedEncs.includes(headerEnc)) {
|
|
192
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", `decryptAuthorizationResponse: JWE enc ${JSON.stringify(headerEnc)} is not in allowlist (${allowedEncs.join(", ")})`);
|
|
193
|
+
}
|
|
194
|
+
let privateKey;
|
|
195
|
+
try {
|
|
196
|
+
privateKey = await importJWK(options.privateKey, headerAlg);
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", `decryptAuthorizationResponse: failed to import private JWK: ${err instanceof Error ? err.message : String(err)}`);
|
|
200
|
+
}
|
|
201
|
+
let plaintextBytes;
|
|
202
|
+
try {
|
|
203
|
+
const decrypted = await compactDecrypt(options.jwe, privateKey, {
|
|
204
|
+
keyManagementAlgorithms: [...allowedAlgs],
|
|
205
|
+
contentEncryptionAlgorithms: [...allowedEncs],
|
|
206
|
+
});
|
|
207
|
+
plaintextBytes = decrypted.plaintext;
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
throw new Oid4vpError("oid4vp.response_encryption_failed", `decryptAuthorizationResponse: JWE decryption failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
211
|
+
}
|
|
212
|
+
let body;
|
|
213
|
+
try {
|
|
214
|
+
const json = new TextDecoder().decode(plaintextBytes);
|
|
215
|
+
const parsed = JSON.parse(json);
|
|
216
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
217
|
+
throw new Error("response payload is not a JSON object");
|
|
218
|
+
}
|
|
219
|
+
body = parsed;
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
throw new Oid4vpError("oid4vp.invalid_json", `decryptAuthorizationResponse: cleartext is not a JSON object: ${err instanceof Error ? err.message : String(err)}`);
|
|
223
|
+
}
|
|
224
|
+
const response = parseJwtResponsePayload(body);
|
|
225
|
+
return { response, header };
|
|
226
|
+
}
|
|
227
|
+
/** Convert the JWE cleartext (already parsed as a JSON object) into an
|
|
228
|
+
* AuthorizationResponse. The shape constraints mirror those enforced
|
|
229
|
+
* by `parseAuthorizationResponseFromParams` for the form-encoded path.
|
|
230
|
+
*/
|
|
231
|
+
function parseJwtResponsePayload(body) {
|
|
232
|
+
const vpTokenRaw = body["vp_token"];
|
|
233
|
+
if (vpTokenRaw === undefined) {
|
|
234
|
+
throw new Oid4vpError("oid4vp.required_field_missing", "Authorization Response is missing required parameter: vp_token");
|
|
235
|
+
}
|
|
236
|
+
let vp_token;
|
|
237
|
+
if (typeof vpTokenRaw === "string") {
|
|
238
|
+
vp_token = vpTokenRaw;
|
|
239
|
+
}
|
|
240
|
+
else if (Array.isArray(vpTokenRaw) &&
|
|
241
|
+
vpTokenRaw.every((v) => typeof v === "string")) {
|
|
242
|
+
vp_token = vpTokenRaw;
|
|
243
|
+
}
|
|
244
|
+
else if (vpTokenRaw !== null &&
|
|
245
|
+
typeof vpTokenRaw === "object" &&
|
|
246
|
+
!Array.isArray(vpTokenRaw)) {
|
|
247
|
+
// DCQL credential map — keys are credential ids. Some wallets wrap
|
|
248
|
+
// each value in a single-element array (mirroring multi-instance
|
|
249
|
+
// presentation futures); flatten to match the form-encoded path.
|
|
250
|
+
const obj = vpTokenRaw;
|
|
251
|
+
const flat = {};
|
|
252
|
+
for (const [id, val] of Object.entries(obj)) {
|
|
253
|
+
if (typeof val === "string") {
|
|
254
|
+
flat[id] = val;
|
|
255
|
+
}
|
|
256
|
+
else if (Array.isArray(val) &&
|
|
257
|
+
val.length === 1 &&
|
|
258
|
+
typeof val[0] === "string") {
|
|
259
|
+
flat[id] = val[0];
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
throw new Oid4vpError("oid4vp.invalid_value_type", `vp_token[${id}] must be a string or single-element array of strings`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
vp_token = flat;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
throw new Oid4vpError("oid4vp.invalid_value_type", "vp_token must be a string, array of strings, or DCQL credential map");
|
|
269
|
+
}
|
|
270
|
+
const isDcqlResponse = typeof vp_token === "object" && !Array.isArray(vp_token);
|
|
271
|
+
let submission;
|
|
272
|
+
const submissionRaw = body["presentation_submission"];
|
|
273
|
+
if (submissionRaw !== undefined) {
|
|
274
|
+
if (submissionRaw === null ||
|
|
275
|
+
typeof submissionRaw !== "object" ||
|
|
276
|
+
Array.isArray(submissionRaw)) {
|
|
277
|
+
throw new Oid4vpError("oid4vp.malformed_submission", "presentation_submission must be a JSON object (DIF Presentation Exchange v2)");
|
|
278
|
+
}
|
|
279
|
+
submission = submissionRaw;
|
|
280
|
+
}
|
|
281
|
+
else if (!isDcqlResponse) {
|
|
282
|
+
throw new Oid4vpError("oid4vp.required_field_missing", "Authorization Response is missing required parameter: presentation_submission");
|
|
283
|
+
}
|
|
284
|
+
const result = { vp_token };
|
|
285
|
+
if (submission !== undefined)
|
|
286
|
+
result.presentation_submission = submission;
|
|
287
|
+
const state = body["state"];
|
|
288
|
+
if (typeof state === "string")
|
|
289
|
+
result.state = state;
|
|
290
|
+
const iss = body["iss"];
|
|
291
|
+
if (typeof iss === "string")
|
|
292
|
+
result.iss = iss;
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=response-jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-jwt.js","sourceRoot":"","sources":["../src/response-jwt.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -7,8 +7,12 @@ import { GramotaError } from "@gramota/core";
|
|
|
7
7
|
* Presentation Definition (§5.4) is modelled but not yet matched/queried —
|
|
8
8
|
* downstream packages will add DIF Presentation Exchange JSONPath support.
|
|
9
9
|
*/
|
|
10
|
-
/** OID4VP §5.4 — `client_id_scheme`
|
|
11
|
-
|
|
10
|
+
/** OID4VP §5.4 + §5.9.3 / HAIP Final 1.0 §5 — `client_id_scheme`
|
|
11
|
+
* enumerated values. HAIP Final 1.0 mandates `x509_hash` for
|
|
12
|
+
* production verifiers; `x509_san_dns` is the legacy prefix the EU
|
|
13
|
+
* reference wallet's emulator build still accepts, kept here for
|
|
14
|
+
* back-compat during the transition. */
|
|
15
|
+
export type ClientIdScheme = "pre-registered" | "redirect_uri" | "https" | "did" | "x509_san_dns" | "x509_san_uri" | "x509_hash" | "verifier_attestation" | (string & {});
|
|
12
16
|
/** OID4VP §6.2 — `response_mode` for the authorization response. */
|
|
13
17
|
export type ResponseMode = "direct_post" | "direct_post.jwt" | "fragment" | "query";
|
|
14
18
|
/** OID4VP §5 — Authorization Request, the bundle a verifier sends to a wallet.
|
|
@@ -108,7 +112,7 @@ export interface SigningCert {
|
|
|
108
112
|
readonly sanDns: string;
|
|
109
113
|
}
|
|
110
114
|
/** Stable codes for `Oid4vpError`. */
|
|
111
|
-
export type Oid4vpErrorCode = "oid4vp.invalid_url" | "oid4vp.required_field_missing" | "oid4vp.unsupported_response_type" | "oid4vp.mutually_exclusive_fields" | "oid4vp.response_uri_required" | "oid4vp.invalid_json" | "oid4vp.invalid_value_type" | "oid4vp.malformed_body" | "oid4vp.malformed_submission" | "oid4vp.cert_generation_failed" | "oid4vp.jar_signing_failed";
|
|
115
|
+
export type Oid4vpErrorCode = "oid4vp.invalid_url" | "oid4vp.required_field_missing" | "oid4vp.unsupported_response_type" | "oid4vp.mutually_exclusive_fields" | "oid4vp.response_uri_required" | "oid4vp.invalid_json" | "oid4vp.invalid_value_type" | "oid4vp.malformed_body" | "oid4vp.malformed_submission" | "oid4vp.cert_generation_failed" | "oid4vp.jar_signing_failed" | "oid4vp.response_encryption_failed";
|
|
112
116
|
export declare class Oid4vpError extends GramotaError {
|
|
113
117
|
readonly code: Oid4vpErrorCode;
|
|
114
118
|
constructor(code: Oid4vpErrorCode, message: string, options?: {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;GAOG;AAEH
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;GAOG;AAEH;;;;wCAIwC;AACxC,MAAM,MAAM,cAAc,GACtB,gBAAgB,GAChB,cAAc,GACd,OAAO,GACP,KAAK,GACL,cAAc,GACd,cAAc,GACd,WAAW,GACX,sBAAsB,GACtB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,oEAAoE;AACpE,MAAM,MAAM,YAAY,GACpB,aAAa,GACb,iBAAiB,GACjB,UAAU,GACV,OAAO,CAAC;AAEZ;;;;2DAI2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,aAAa,EAAE,UAAU,CAAC;IAC1B,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB;uEACmE;IACnE,gBAAgB,CAAC,EAAE,cAAc,CAAC;IAClC,wEAAwE;IACxE,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;mCAC+B;IAC/B,uBAAuB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,gFAAgF;IAChF,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;4DACwD;IACxD,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/C,8CAA8C;IAC9C,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD;+BAC2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxE;gEAC4D;IAC5D,uBAAuB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,oCAAoC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;sEACkE;IAClE,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC;;2CAEuC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,sCAAsC;AACtC,MAAM,MAAM,eAAe,GACvB,oBAAoB,GACpB,+BAA+B,GAC/B,kCAAkC,GAClC,kCAAkC,GAClC,8BAA8B,GAC9B,qBAAqB,GACrB,2BAA2B,GAC3B,uBAAuB,GACvB,6BAA6B,GAC7B,+BAA+B,GAC/B,2BAA2B,GAC3B,mCAAmC,CAAC;AAExC,qBAAa,WAAY,SAAQ,YAAY;IAC3C,SAAkB,IAAI,EAAE,eAAe,CAAC;gBAGtC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAMhC"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAoJ7C,MAAM,OAAO,WAAY,SAAQ,YAAY;IACzB,IAAI,CAAkB;IAExC,YACE,IAAqB,EACrB,OAAe,EACf,OAA6B;QAE7B,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gramota/oid4vp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "OpenID for Verifiable Presentations transport — authorization request/response wire format for EUDIW.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"@peculiar/x509": "^2.0.0",
|
|
20
20
|
"jose": "^5.9.6",
|
|
21
21
|
"reflect-metadata": "^0.2.0",
|
|
22
|
-
"@gramota/core": "0.2.
|
|
23
|
-
"@gramota/jose": "0.
|
|
22
|
+
"@gramota/core": "0.2.1",
|
|
23
|
+
"@gramota/jose": "0.3.0"
|
|
24
24
|
},
|
|
25
25
|
"sideEffects": [
|
|
26
26
|
"./dist/cert.js"
|