@openid4vc/openid4vp 0.3.0-alpha-20250320222745 → 0.3.0-alpha-20250321120839
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.mts +6830 -1196
- package/dist/index.d.ts +6830 -1196
- package/dist/index.js +237 -212
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +219 -194
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ __export(src_exports, {
|
|
|
60
60
|
module.exports = __toCommonJS(src_exports);
|
|
61
61
|
|
|
62
62
|
// src/client-identifier-scheme/parse-client-identifier-scheme.ts
|
|
63
|
-
var
|
|
63
|
+
var import_oauth23 = require("@openid4vc/oauth2");
|
|
64
64
|
var import_utils4 = require("@openid4vc/utils");
|
|
65
65
|
|
|
66
66
|
// src/authorization-request/z-authorization-request-dc-api.ts
|
|
@@ -200,37 +200,31 @@ var zOpenid4vpAuthorizationRequestFromUriParams = import_zod4.z.string().url().t
|
|
|
200
200
|
);
|
|
201
201
|
|
|
202
202
|
// src/authorization-request/z-authorization-request-dc-api.ts
|
|
203
|
+
var zOpenid4vpResponseModeDcApi = import_zod5.z.enum(["dc_api", "dc_api.jwt", "w3c_dc_api.jwt", "w3c_dc_api"]);
|
|
203
204
|
var zOpenid4vpAuthorizationRequestDcApi = zOpenid4vpAuthorizationRequest.pick({
|
|
204
|
-
client_id: true,
|
|
205
205
|
response_type: true,
|
|
206
|
-
response_mode: true,
|
|
207
206
|
nonce: true,
|
|
208
207
|
presentation_definition: true,
|
|
209
208
|
client_metadata: true,
|
|
210
209
|
transaction_data: true,
|
|
211
210
|
dcql_query: true,
|
|
212
|
-
trust_chain: true
|
|
211
|
+
trust_chain: true,
|
|
212
|
+
state: true
|
|
213
213
|
}).extend({
|
|
214
214
|
client_id: import_zod5.z.optional(import_zod5.z.string()),
|
|
215
215
|
expected_origins: import_zod5.z.array(import_zod5.z.string()).optional(),
|
|
216
|
-
response_mode:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"verifier_attestation",
|
|
223
|
-
"x509_san_dns",
|
|
224
|
-
"x509_san_uri"
|
|
225
|
-
]).optional()
|
|
226
|
-
}).strip();
|
|
216
|
+
response_mode: zOpenid4vpResponseModeDcApi,
|
|
217
|
+
// Not allowed with dc_api, but added to make working with interfaces easier
|
|
218
|
+
client_id_scheme: import_zod5.z.never().optional(),
|
|
219
|
+
scope: import_zod5.z.never().optional()
|
|
220
|
+
// TODO: should we disallow any properties specifically, such as redirect_uri and response_uri?
|
|
221
|
+
});
|
|
227
222
|
function isOpenid4vpAuthorizationRequestDcApi(request) {
|
|
228
|
-
return request.response_mode
|
|
223
|
+
return request.response_mode !== void 0 && zOpenid4vpResponseModeDcApi.options.includes(
|
|
224
|
+
request.response_mode
|
|
225
|
+
);
|
|
229
226
|
}
|
|
230
227
|
|
|
231
|
-
// src/version.ts
|
|
232
|
-
var import_oauth23 = require("@openid4vc/oauth2");
|
|
233
|
-
|
|
234
228
|
// src/client-identifier-scheme/z-client-id-scheme.ts
|
|
235
229
|
var import_zod6 = require("zod");
|
|
236
230
|
var zClientIdScheme = import_zod6.z.enum([
|
|
@@ -243,155 +237,114 @@ var zClientIdScheme = import_zod6.z.enum([
|
|
|
243
237
|
"x509_san_uri",
|
|
244
238
|
"web-origin"
|
|
245
239
|
]);
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
requirements.push([">=", 23]);
|
|
256
|
-
}
|
|
257
|
-
if (isOpenid4vpAuthorizationRequestDcApi(request) && (request.transaction_data || request.dcql_query)) {
|
|
258
|
-
requirements.push([">=", 23]);
|
|
259
|
-
}
|
|
260
|
-
if (request.dcql_query) {
|
|
261
|
-
requirements.push([">=", 22]);
|
|
262
|
-
}
|
|
263
|
-
if (request.transaction_data) {
|
|
264
|
-
requirements.push([">=", 22]);
|
|
265
|
-
}
|
|
266
|
-
if (request.client_id_scheme) {
|
|
267
|
-
requirements.push(["<", 22]);
|
|
268
|
-
}
|
|
269
|
-
if (request.client_id) {
|
|
270
|
-
const colonIndex = request.client_id.indexOf(":");
|
|
271
|
-
const schemePart = request.client_id.substring(0, colonIndex);
|
|
272
|
-
const parsedScheme = zClientIdScheme.safeParse(schemePart);
|
|
273
|
-
if (parsedScheme.success && parsedScheme.data !== "did" && parsedScheme.data !== "https") {
|
|
274
|
-
requirements.push([">=", 22]);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
if (!request.client_id) {
|
|
278
|
-
requirements.push([">=", 21]);
|
|
279
|
-
}
|
|
280
|
-
if ("client_metadata_uri" in request) {
|
|
281
|
-
requirements.push(["<", 21]);
|
|
282
|
-
}
|
|
283
|
-
if (isOpenid4vpAuthorizationRequestDcApi(request)) {
|
|
284
|
-
requirements.push([">=", 21]);
|
|
285
|
-
}
|
|
286
|
-
if ("request_uri_method" in request || "wallet_nonce" in request) {
|
|
287
|
-
requirements.push([">=", 21]);
|
|
288
|
-
}
|
|
289
|
-
if (request.client_id_scheme === "verifier_attestation") {
|
|
290
|
-
requirements.push([">=", 20]);
|
|
291
|
-
}
|
|
292
|
-
if (request.client_id_scheme === "x509_san_dns" || request.client_id_scheme === "x509_san_uri") {
|
|
293
|
-
requirements.push([">=", 19]);
|
|
294
|
-
}
|
|
295
|
-
const lessThanVersions = requirements.filter(([operator]) => operator === "<").map(([_, version]) => version);
|
|
296
|
-
const greaterThanVersions = requirements.filter(([operator]) => operator === ">=").map(([_, version]) => version);
|
|
297
|
-
const highestPossibleVersion = lessThanVersions.length > 0 ? Math.max(Math.min(...lessThanVersions) - 1, 18) : 24;
|
|
298
|
-
const lowestRequiredVersion = greaterThanVersions.length > 0 ? Math.max(...greaterThanVersions) : 18;
|
|
299
|
-
if (lowestRequiredVersion > highestPossibleVersion) {
|
|
300
|
-
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
301
|
-
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
302
|
-
error_description: "Could not infer openid4vp version from the openid4vp request payload."
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
return highestPossibleVersion;
|
|
306
|
-
}
|
|
240
|
+
var zLegacyClientIdScheme = import_zod6.z.enum([
|
|
241
|
+
"pre-registered",
|
|
242
|
+
"redirect_uri",
|
|
243
|
+
"entity_id",
|
|
244
|
+
"did",
|
|
245
|
+
"verifier_attestation",
|
|
246
|
+
"x509_san_dns",
|
|
247
|
+
"x509_san_uri"
|
|
248
|
+
]);
|
|
307
249
|
|
|
308
250
|
// src/client-identifier-scheme/parse-client-identifier-scheme.ts
|
|
309
251
|
function getOpenid4vpClientId(options) {
|
|
310
|
-
const version = parseAuthorizationRequestVersion(options.authorizationRequestPayload);
|
|
311
|
-
if (version < 22) {
|
|
312
|
-
return getLegacyClientId(options);
|
|
313
|
-
}
|
|
314
252
|
if (isOpenid4vpAuthorizationRequestDcApi(options.authorizationRequestPayload)) {
|
|
315
253
|
if (!options.origin) {
|
|
316
|
-
throw new
|
|
317
|
-
error:
|
|
254
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
255
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
318
256
|
error_description: "Failed to parse client identifier. 'origin' is required for requests with response_mode 'dc_api' and 'dc_api.jwt'"
|
|
319
257
|
});
|
|
320
258
|
}
|
|
321
|
-
|
|
322
|
-
|
|
259
|
+
return {
|
|
260
|
+
clientId: options.authorizationRequestPayload.client_id ?? `web-origin:${options.origin}`
|
|
261
|
+
};
|
|
323
262
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
263
|
+
if (!options.authorizationRequestPayload.client_id) {
|
|
264
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
265
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
266
|
+
error_description: `Failed to parse client identifier. Missing required client_id parameter for response_mode '${options.authorizationRequestPayload.response_mode}'.`
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
if (options.authorizationRequestPayload.client_id_scheme) {
|
|
270
|
+
const parsedClientIdScheme = zLegacyClientIdScheme.safeParse(options.authorizationRequestPayload.client_id_scheme);
|
|
271
|
+
if (!parsedClientIdScheme.success) {
|
|
272
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
273
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
274
|
+
error_description: `Failed to parse client identifier. Unsupported client_id_scheme value '${options.authorizationRequestPayload.client_id_scheme}'.`
|
|
334
275
|
});
|
|
335
276
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
return
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
277
|
+
const clientIdScheme = parsedClientIdScheme.data === "entity_id" ? "https" : parsedClientIdScheme.data;
|
|
278
|
+
if (clientIdScheme === "https" || clientIdScheme === "did" || clientIdScheme === "pre-registered") {
|
|
279
|
+
return { clientId: options.authorizationRequestPayload.client_id };
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
clientId: `${clientIdScheme}:${options.authorizationRequestPayload.client_id}`,
|
|
283
|
+
legacyClientId: options.authorizationRequestPayload.client_id
|
|
284
|
+
};
|
|
344
285
|
}
|
|
345
|
-
return
|
|
286
|
+
return {
|
|
287
|
+
clientId: options.authorizationRequestPayload.client_id
|
|
288
|
+
};
|
|
346
289
|
}
|
|
347
290
|
function parseClientIdentifier(options, parserConfig) {
|
|
348
|
-
const { authorizationRequestPayload, jar } = options;
|
|
291
|
+
const { authorizationRequestPayload, jar, origin } = options;
|
|
349
292
|
const parserConfigWithDefaults = {
|
|
350
293
|
supportedSchemes: parserConfig?.supportedSchemes || Object.values(zClientIdScheme.options)
|
|
351
294
|
};
|
|
352
|
-
const clientId = getOpenid4vpClientId(
|
|
295
|
+
const { clientId, legacyClientId } = getOpenid4vpClientId({
|
|
296
|
+
authorizationRequestPayload,
|
|
297
|
+
origin
|
|
298
|
+
});
|
|
353
299
|
const colonIndex = clientId.indexOf(":");
|
|
354
300
|
if (colonIndex === -1) {
|
|
355
301
|
return {
|
|
356
302
|
scheme: "pre-registered",
|
|
357
303
|
identifier: clientId,
|
|
358
304
|
originalValue: clientId,
|
|
305
|
+
legacyClientId,
|
|
359
306
|
clientMetadata: authorizationRequestPayload.client_metadata
|
|
360
307
|
};
|
|
361
308
|
}
|
|
362
309
|
const schemePart = clientId.substring(0, colonIndex);
|
|
363
310
|
const identifierPart = clientId.substring(colonIndex + 1);
|
|
364
311
|
if (!parserConfigWithDefaults.supportedSchemes.includes(schemePart)) {
|
|
365
|
-
throw new
|
|
366
|
-
error:
|
|
312
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
313
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
367
314
|
error_description: `Unsupported client identifier scheme. ${schemePart} is not supported.`
|
|
368
315
|
});
|
|
369
316
|
}
|
|
370
317
|
const scheme = schemePart;
|
|
371
318
|
if (scheme === "https") {
|
|
372
|
-
if (!
|
|
373
|
-
throw new
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
319
|
+
if (!import_utils4.zHttpsUrl.safeParse(clientId).success) {
|
|
320
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError(
|
|
321
|
+
{
|
|
322
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
323
|
+
error_description: "Invalid client identifier. Client identifier must start with https://"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
internalMessage: `Insecure http:// urls can be enabled by setting the 'allowInsecureUrls' option using setGlobalConfig`
|
|
327
|
+
}
|
|
328
|
+
);
|
|
377
329
|
}
|
|
378
330
|
return {
|
|
379
331
|
scheme,
|
|
380
332
|
identifier: clientId,
|
|
381
333
|
originalValue: clientId,
|
|
334
|
+
legacyClientId,
|
|
382
335
|
trustChain: authorizationRequestPayload.trust_chain
|
|
383
336
|
};
|
|
384
337
|
}
|
|
385
338
|
if (scheme === "redirect_uri") {
|
|
386
339
|
if (jar) {
|
|
387
|
-
throw new
|
|
388
|
-
error:
|
|
340
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
341
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
389
342
|
error_description: 'Using client identifier scheme "redirect_uri" the request MUST NOT be signed.'
|
|
390
343
|
});
|
|
391
344
|
}
|
|
392
345
|
if (isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
393
|
-
throw new
|
|
394
|
-
error:
|
|
346
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
347
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
395
348
|
error_description: `The client identifier scheme 'redirect_uri' is not supported when using the dc_api response mode.`
|
|
396
349
|
});
|
|
397
350
|
}
|
|
@@ -399,31 +352,32 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
399
352
|
scheme,
|
|
400
353
|
identifier: identifierPart,
|
|
401
354
|
originalValue: clientId,
|
|
355
|
+
legacyClientId,
|
|
402
356
|
redirectUri: authorizationRequestPayload.redirect_uri ?? authorizationRequestPayload.response_uri
|
|
403
357
|
};
|
|
404
358
|
}
|
|
405
359
|
if (scheme === "did") {
|
|
406
360
|
if (!jar) {
|
|
407
|
-
throw new
|
|
408
|
-
error:
|
|
361
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
362
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
409
363
|
error_description: 'Using client identifier scheme "did" requires a signed JAR request.'
|
|
410
364
|
});
|
|
411
365
|
}
|
|
412
366
|
if (!clientId.startsWith("did:")) {
|
|
413
|
-
throw new
|
|
414
|
-
error:
|
|
367
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
368
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
415
369
|
error_description: "Invalid client identifier. Client identifier must start with 'did:'"
|
|
416
370
|
});
|
|
417
371
|
}
|
|
418
372
|
if (!jar.signer.publicJwk.kid) {
|
|
419
|
-
throw new
|
|
420
|
-
error:
|
|
373
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
374
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
421
375
|
error_description: `Missing required 'kid' for client identifier scheme: did`
|
|
422
376
|
});
|
|
423
377
|
}
|
|
424
378
|
if (!jar.signer.publicJwk.kid?.startsWith(clientId)) {
|
|
425
|
-
throw new
|
|
426
|
-
error:
|
|
379
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
380
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
427
381
|
error_description: 'With client identifier scheme "did" the JAR request must be signed by the same DID as the client identifier.'
|
|
428
382
|
});
|
|
429
383
|
}
|
|
@@ -431,27 +385,28 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
431
385
|
scheme,
|
|
432
386
|
identifier: clientId,
|
|
433
387
|
originalValue: clientId,
|
|
388
|
+
legacyClientId,
|
|
434
389
|
didUrl: jar.signer.publicJwk.kid
|
|
435
390
|
};
|
|
436
391
|
}
|
|
437
392
|
if (scheme === "x509_san_dns" || scheme === "x509_san_uri") {
|
|
438
393
|
if (!jar) {
|
|
439
|
-
throw new
|
|
440
|
-
error:
|
|
394
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
395
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
441
396
|
error_description: 'Using client identifier scheme "x509_san_dns" or "x509_san_uri" requires a signed JAR request.'
|
|
442
397
|
});
|
|
443
398
|
}
|
|
444
399
|
if (jar.signer.method !== "x5c") {
|
|
445
|
-
throw new
|
|
446
|
-
error:
|
|
400
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
401
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
447
402
|
error_description: "Something went wrong. The JWT signer method is not x5c but the client identifier scheme is x509_san_dns."
|
|
448
403
|
});
|
|
449
404
|
}
|
|
450
405
|
if (scheme === "x509_san_dns") {
|
|
451
406
|
if (!options.callbacks.getX509CertificateMetadata) {
|
|
452
|
-
throw new
|
|
407
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError(
|
|
453
408
|
{
|
|
454
|
-
error:
|
|
409
|
+
error: import_oauth23.Oauth2ErrorCodes.ServerError
|
|
455
410
|
},
|
|
456
411
|
{
|
|
457
412
|
internalMessage: "Missing required 'getX509CertificateMetadata' callback for verification of 'x509_san_dns' client id scheme"
|
|
@@ -460,25 +415,25 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
460
415
|
}
|
|
461
416
|
const { sanDnsNames } = options.callbacks.getX509CertificateMetadata(jar.signer.x5c[0]);
|
|
462
417
|
if (!sanDnsNames.includes(identifierPart)) {
|
|
463
|
-
throw new
|
|
464
|
-
error:
|
|
418
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
419
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
465
420
|
error_description: `Invalid client identifier. One of the leaf certificates san dns names [${sanDnsNames.join(", ")}] must match the client identifier '${identifierPart}'. `
|
|
466
421
|
});
|
|
467
422
|
}
|
|
468
423
|
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
469
424
|
const uri = authorizationRequestPayload.redirect_uri ?? authorizationRequestPayload.response_uri;
|
|
470
425
|
if (!uri || new import_utils4.URL(uri).hostname !== identifierPart) {
|
|
471
|
-
throw new
|
|
472
|
-
error:
|
|
426
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
427
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
473
428
|
error_description: "Invalid client identifier. The fully qualified domain name of the redirect_uri value MUST match the Client Identifier without the prefix x509_san_dns."
|
|
474
429
|
});
|
|
475
430
|
}
|
|
476
431
|
}
|
|
477
432
|
} else if (scheme === "x509_san_uri") {
|
|
478
433
|
if (!options.callbacks.getX509CertificateMetadata) {
|
|
479
|
-
throw new
|
|
434
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError(
|
|
480
435
|
{
|
|
481
|
-
error:
|
|
436
|
+
error: import_oauth23.Oauth2ErrorCodes.ServerError
|
|
482
437
|
},
|
|
483
438
|
{
|
|
484
439
|
internalMessage: "Missing required 'getX509CertificateMetadata' callback for verification of 'x509_san_uri' client id scheme"
|
|
@@ -487,16 +442,16 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
487
442
|
}
|
|
488
443
|
const { sanUriNames } = options.callbacks.getX509CertificateMetadata(jar.signer.x5c[0]);
|
|
489
444
|
if (!sanUriNames.includes(identifierPart)) {
|
|
490
|
-
throw new
|
|
491
|
-
error:
|
|
445
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
446
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
492
447
|
error_description: `Invalid client identifier. One of the leaf certificates san uri names [${sanUriNames.join(", ")}] must match the client identifier '${identifierPart}'.`
|
|
493
448
|
});
|
|
494
449
|
}
|
|
495
450
|
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
496
451
|
const uri = authorizationRequestPayload.redirect_uri || authorizationRequestPayload.response_uri;
|
|
497
452
|
if (!uri || uri !== identifierPart) {
|
|
498
|
-
throw new
|
|
499
|
-
error:
|
|
453
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
454
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
500
455
|
error_description: "The redirect_uri value MUST match the Client Identifier without the prefix x509_san_uri"
|
|
501
456
|
});
|
|
502
457
|
}
|
|
@@ -506,6 +461,7 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
506
461
|
scheme,
|
|
507
462
|
identifier: identifierPart,
|
|
508
463
|
originalValue: clientId,
|
|
464
|
+
legacyClientId,
|
|
509
465
|
x5c: jar.signer.x5c
|
|
510
466
|
};
|
|
511
467
|
}
|
|
@@ -514,13 +470,14 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
514
470
|
scheme,
|
|
515
471
|
identifier: identifierPart,
|
|
516
472
|
originalValue: clientId,
|
|
473
|
+
legacyClientId,
|
|
517
474
|
clientMetadata: authorizationRequestPayload.client_metadata
|
|
518
475
|
};
|
|
519
476
|
}
|
|
520
477
|
if (scheme === "verifier_attestation") {
|
|
521
478
|
if (!jar) {
|
|
522
|
-
throw new
|
|
523
|
-
error:
|
|
479
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
480
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
524
481
|
error_description: 'Using client identifier scheme "verifier_attestation" requires a signed JAR request.'
|
|
525
482
|
});
|
|
526
483
|
}
|
|
@@ -528,12 +485,13 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
528
485
|
return {
|
|
529
486
|
scheme,
|
|
530
487
|
identifier: identifierPart,
|
|
488
|
+
legacyClientId,
|
|
531
489
|
originalValue: clientId
|
|
532
490
|
};
|
|
533
491
|
}
|
|
534
492
|
|
|
535
493
|
// src/jarm/jarm-authorization-response/verify-jarm-authorization-response.ts
|
|
536
|
-
var
|
|
494
|
+
var import_oauth26 = require("@openid4vc/oauth2");
|
|
537
495
|
var import_zod8 = __toESM(require("zod"));
|
|
538
496
|
|
|
539
497
|
// src/jarm/jarm-extract-jwks.ts
|
|
@@ -549,25 +507,25 @@ function extractJwksFromClientMetadata(clientMetadata) {
|
|
|
549
507
|
}
|
|
550
508
|
|
|
551
509
|
// src/jarm/jarm-authorization-response/jarm-validate-authorization-response.ts
|
|
552
|
-
var
|
|
510
|
+
var import_oauth25 = require("@openid4vc/oauth2");
|
|
553
511
|
var import_utils5 = require("@openid4vc/utils");
|
|
554
512
|
|
|
555
513
|
// src/jarm/jarm-authorization-response/z-jarm-authorization-response.ts
|
|
556
|
-
var
|
|
514
|
+
var import_oauth24 = require("@openid4vc/oauth2");
|
|
557
515
|
var import_zod7 = require("zod");
|
|
558
|
-
var zJarmHeader = import_zod7.z.object({ ...
|
|
516
|
+
var zJarmHeader = import_zod7.z.object({ ...import_oauth24.zJwtHeader.shape, apu: import_zod7.z.string().optional(), apv: import_zod7.z.string().optional() });
|
|
559
517
|
var zJarmAuthorizationResponse = import_zod7.z.object({
|
|
560
518
|
/**
|
|
561
519
|
* iss: The issuer URL of the authorization server that created the response
|
|
562
520
|
* aud: The client_id of the client the response is intended for
|
|
563
521
|
* exp: The expiration time of the JWT. A maximum JWT lifetime of 10 minutes is RECOMMENDED.
|
|
564
522
|
*/
|
|
565
|
-
...
|
|
566
|
-
...
|
|
523
|
+
...import_oauth24.zJwtPayload.shape,
|
|
524
|
+
...import_oauth24.zJwtPayload.pick({ iss: true, aud: true, exp: true }).required().shape,
|
|
567
525
|
state: import_zod7.z.optional(import_zod7.z.string())
|
|
568
526
|
}).passthrough();
|
|
569
527
|
var zJarmAuthorizationResponseEncryptedOnly = import_zod7.z.object({
|
|
570
|
-
...
|
|
528
|
+
...import_oauth24.zJwtPayload.shape,
|
|
571
529
|
state: import_zod7.z.optional(import_zod7.z.string())
|
|
572
530
|
}).passthrough();
|
|
573
531
|
|
|
@@ -578,12 +536,12 @@ var jarmAuthorizationResponseValidate = (options) => {
|
|
|
578
536
|
return;
|
|
579
537
|
}
|
|
580
538
|
if (expectedClientId !== authorizationResponse.aud) {
|
|
581
|
-
throw new
|
|
539
|
+
throw new import_oauth25.Oauth2Error(
|
|
582
540
|
`Invalid 'aud' claim in JARM authorization response. Expected '${expectedClientId}' received '${JSON.stringify(authorizationResponse.aud)}'.`
|
|
583
541
|
);
|
|
584
542
|
}
|
|
585
543
|
if (authorizationResponse.exp !== void 0 && authorizationResponse.exp < (0, import_utils5.dateToSeconds)()) {
|
|
586
|
-
throw new
|
|
544
|
+
throw new import_oauth25.Oauth2Error("Jarm auth response is expired.");
|
|
587
545
|
}
|
|
588
546
|
};
|
|
589
547
|
|
|
@@ -602,37 +560,37 @@ var decryptJarmAuthorizationResponseJwt = async (options) => {
|
|
|
602
560
|
}).encJwk : void 0;
|
|
603
561
|
const result = await callbacks.decryptJwe(jarmAuthorizationResponseJwt, { jwk: encryptionJwk });
|
|
604
562
|
if (!result.decrypted) {
|
|
605
|
-
throw new
|
|
563
|
+
throw new import_oauth26.Oauth2Error("Failed to decrypt jarm auth response.");
|
|
606
564
|
}
|
|
607
565
|
return result.payload;
|
|
608
566
|
};
|
|
609
567
|
async function verifyJarmAuthorizationResponse(options) {
|
|
610
568
|
const { jarmAuthorizationResponseJwt, callbacks, expectedClientId, authorizationRequestPayload } = options;
|
|
611
|
-
const requestDataIsEncrypted =
|
|
569
|
+
const requestDataIsEncrypted = import_oauth26.zCompactJwe.safeParse(jarmAuthorizationResponseJwt).success;
|
|
612
570
|
const decryptedRequestData = requestDataIsEncrypted ? await decryptJarmAuthorizationResponseJwt({
|
|
613
571
|
jarmAuthorizationResponseJwt,
|
|
614
572
|
callbacks,
|
|
615
573
|
authorizationRequestPayload
|
|
616
574
|
}) : jarmAuthorizationResponseJwt;
|
|
617
|
-
const responseIsSigned =
|
|
575
|
+
const responseIsSigned = import_oauth26.zCompactJwt.safeParse(decryptedRequestData).success;
|
|
618
576
|
if (!requestDataIsEncrypted && !responseIsSigned) {
|
|
619
|
-
throw new
|
|
577
|
+
throw new import_oauth26.Oauth2Error("Jarm Auth Response must be either encrypted, signed, or signed and encrypted.");
|
|
620
578
|
}
|
|
621
579
|
let jarmAuthorizationResponse;
|
|
622
580
|
if (responseIsSigned) {
|
|
623
|
-
const { header: jwsProtectedHeader, payload: jwsPayload } = (0,
|
|
581
|
+
const { header: jwsProtectedHeader, payload: jwsPayload } = (0, import_oauth26.decodeJwt)({
|
|
624
582
|
jwt: decryptedRequestData,
|
|
625
|
-
headerSchema: import_zod8.default.object({ ...
|
|
583
|
+
headerSchema: import_zod8.default.object({ ...import_oauth26.zJwtHeader.shape, kid: import_zod8.default.string() })
|
|
626
584
|
});
|
|
627
585
|
const response = zJarmAuthorizationResponse.parse(jwsPayload);
|
|
628
|
-
const jwtSigner = (0,
|
|
586
|
+
const jwtSigner = (0, import_oauth26.jwtSignerFromJwt)({ header: jwsProtectedHeader, payload: jwsPayload });
|
|
629
587
|
const verificationResult = await options.callbacks.verifyJwt(jwtSigner, {
|
|
630
588
|
compact: decryptedRequestData,
|
|
631
589
|
header: jwsProtectedHeader,
|
|
632
590
|
payload: jwsPayload
|
|
633
591
|
});
|
|
634
592
|
if (!verificationResult.verified) {
|
|
635
|
-
throw new
|
|
593
|
+
throw new import_oauth26.Oauth2Error("Jarm Auth Response is not valid.");
|
|
636
594
|
}
|
|
637
595
|
jarmAuthorizationResponse = response;
|
|
638
596
|
} else {
|
|
@@ -649,17 +607,17 @@ async function verifyJarmAuthorizationResponse(options) {
|
|
|
649
607
|
}
|
|
650
608
|
|
|
651
609
|
// src/authorization-request/create-authorization-request.ts
|
|
652
|
-
var
|
|
610
|
+
var import_oauth210 = require("@openid4vc/oauth2");
|
|
653
611
|
var import_utils7 = require("@openid4vc/utils");
|
|
654
612
|
|
|
655
613
|
// src/jar/create-jar-authorization-request.ts
|
|
656
|
-
var
|
|
614
|
+
var import_oauth27 = require("@openid4vc/oauth2");
|
|
657
615
|
async function createJarAuthorizationRequest(options) {
|
|
658
616
|
const { jwtSigner, jweEncryptor, authorizationRequestPayload, requestUri, callbacks } = options;
|
|
659
617
|
let authorizationRequestJwt;
|
|
660
618
|
let encryptionJwk;
|
|
661
619
|
const { jwt, signerJwk } = await callbacks.signJwt(jwtSigner, {
|
|
662
|
-
header: { ...(0,
|
|
620
|
+
header: { ...(0, import_oauth27.jwtHeaderFromJwtSigner)(jwtSigner), typ: "oauth-authz-req+jwt" },
|
|
663
621
|
payload: { ...options.additionalJwtPayload, ...authorizationRequestPayload }
|
|
664
622
|
});
|
|
665
623
|
authorizationRequestJwt = jwt;
|
|
@@ -674,94 +632,94 @@ async function createJarAuthorizationRequest(options) {
|
|
|
674
632
|
}
|
|
675
633
|
|
|
676
634
|
// src/authorization-request/validate-authorization-request.ts
|
|
677
|
-
var
|
|
635
|
+
var import_oauth28 = require("@openid4vc/oauth2");
|
|
678
636
|
var import_utils6 = require("@openid4vc/utils");
|
|
679
637
|
var validateOpenid4vpAuthorizationRequestPayload = (options) => {
|
|
680
638
|
const { params, walletVerificationOptions } = options;
|
|
681
639
|
if (!params.redirect_uri && !params.response_uri) {
|
|
682
|
-
throw new
|
|
683
|
-
error:
|
|
640
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
641
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
684
642
|
error_description: `Missing required 'redirect_uri' or 'response_uri' in openid4vp authorization request.`
|
|
685
643
|
});
|
|
686
644
|
}
|
|
687
645
|
if (params.response_uri && !["direct_post", "direct_post.jwt"].find((mode) => mode === params.response_mode)) {
|
|
688
|
-
throw new
|
|
689
|
-
error:
|
|
646
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
647
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
690
648
|
error_description: `The 'response_mode' parameter MUST be 'direct_post' or 'direct_post.jwt' when 'response_uri' is provided. Current: ${params.response_mode}`
|
|
691
649
|
});
|
|
692
650
|
}
|
|
693
651
|
if ([params.presentation_definition_uri, params.presentation_definition, params.dcql_query, params.scope].filter(
|
|
694
652
|
Boolean
|
|
695
653
|
).length > 1) {
|
|
696
|
-
throw new
|
|
697
|
-
error:
|
|
654
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
655
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
698
656
|
error_description: "Exactly one of the following parameters MUST be present in the authorization request: dcql_query, presentation_definition, presentation_definition_uri, or a scope value representing a Presentation Definition."
|
|
699
657
|
});
|
|
700
658
|
}
|
|
701
659
|
if (params.request_uri_method && !params.request_uri) {
|
|
702
|
-
throw new
|
|
703
|
-
error:
|
|
660
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
661
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
704
662
|
error_description: 'The "request_uri_method" parameter MUST NOT be present in the authorization request if the "request_uri" parameter is not present.'
|
|
705
663
|
});
|
|
706
664
|
}
|
|
707
665
|
if (params.request_uri_method && !["GET", "POST"].includes(params.request_uri_method)) {
|
|
708
|
-
throw new
|
|
709
|
-
error:
|
|
666
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
667
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequestUriMethod,
|
|
710
668
|
error_description: `The 'request_uri_method' parameter MUST be 'GET' or 'POST'. Current: ${params.request_uri_method}`
|
|
711
669
|
});
|
|
712
670
|
}
|
|
713
671
|
if (params.trust_chain && !import_utils6.zHttpsUrl.safeParse(params.client_id).success) {
|
|
714
|
-
throw new
|
|
715
|
-
error:
|
|
672
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
673
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
716
674
|
error_description: 'The "trust_chain" parameter MUST NOT be present in the authorization request if the "client_id" is not an OpenId Federation Entity Identifier starting with http:// or https://.'
|
|
717
675
|
});
|
|
718
676
|
}
|
|
719
677
|
if (walletVerificationOptions?.expectedNonce && !params.wallet_nonce) {
|
|
720
|
-
throw new
|
|
721
|
-
error:
|
|
678
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
679
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
722
680
|
error_description: 'The "wallet_nonce" parameter MUST be present in the authorization request when the "expectedNonce" parameter is provided.'
|
|
723
681
|
});
|
|
724
682
|
}
|
|
725
683
|
if (walletVerificationOptions?.expectedNonce !== params.wallet_nonce) {
|
|
726
|
-
throw new
|
|
727
|
-
error:
|
|
684
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
685
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
728
686
|
error_description: 'The "wallet_nonce" parameter MUST match the "expectedNonce" parameter when the "expectedNonce" parameter is provided.'
|
|
729
687
|
});
|
|
730
688
|
}
|
|
731
689
|
if (params.client_id.startsWith("web-origin:")) {
|
|
732
|
-
throw new
|
|
733
|
-
error:
|
|
690
|
+
throw new import_oauth28.Oauth2ServerErrorResponseError({
|
|
691
|
+
error: import_oauth28.Oauth2ErrorCodes.InvalidRequest,
|
|
734
692
|
error_description: `The 'client_id' parameter MUST NOT use client identifier scheme 'web-origin' when not using the dc_api response mode. Current: ${params.client_id}`
|
|
735
693
|
});
|
|
736
694
|
}
|
|
737
695
|
};
|
|
738
696
|
|
|
739
697
|
// src/authorization-request/validate-authorization-request-dc-api.ts
|
|
740
|
-
var
|
|
698
|
+
var import_oauth29 = require("@openid4vc/oauth2");
|
|
741
699
|
var validateOpenid4vpAuthorizationRequestDcApiPayload = (options) => {
|
|
742
700
|
const { params, isJarRequest, disableOriginValidation, origin } = options;
|
|
743
701
|
if (isJarRequest && !params.expected_origins) {
|
|
744
|
-
throw new
|
|
745
|
-
error:
|
|
702
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
703
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
746
704
|
error_description: `The 'expected_origins' parameter MUST be present when using the dc_api response mode in combinaction with jar.`
|
|
747
705
|
});
|
|
748
706
|
}
|
|
749
707
|
if ([params.presentation_definition, params.dcql_query].filter(Boolean).length !== 1) {
|
|
750
|
-
throw new
|
|
751
|
-
error:
|
|
708
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
709
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
752
710
|
error_description: "Exactly one of the following parameters MUST be present in the Authorization Request: dcql_query or presentation_definition"
|
|
753
711
|
});
|
|
754
712
|
}
|
|
755
713
|
if (params.expected_origins && !disableOriginValidation) {
|
|
756
714
|
if (!origin) {
|
|
757
|
-
throw new
|
|
758
|
-
error:
|
|
715
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
716
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
759
717
|
error_description: `Failed to validate the 'origin' of the authorization request. The 'origin' was not provided.`
|
|
760
718
|
});
|
|
761
719
|
}
|
|
762
720
|
if (params.expected_origins && !params.expected_origins.includes(origin)) {
|
|
763
|
-
throw new
|
|
764
|
-
error:
|
|
721
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
722
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
765
723
|
error_description: `The 'expected_origins' parameter MUST include the origin of the authorization request. Current: ${params.expected_origins.join(", ")}`
|
|
766
724
|
});
|
|
767
725
|
}
|
|
@@ -780,7 +738,7 @@ async function createOpenid4vpAuthorizationRequest(options) {
|
|
|
780
738
|
"Invalid authorization request. Could not parse openid4vp dc_api authorization request."
|
|
781
739
|
);
|
|
782
740
|
if (jar && !authorizationRequestPayload.expected_origins) {
|
|
783
|
-
throw new
|
|
741
|
+
throw new import_oauth210.Oauth2Error(
|
|
784
742
|
`The 'expected_origins' parameter MUST be present when using the dc_api response mode in combination with jar.`
|
|
785
743
|
);
|
|
786
744
|
}
|
|
@@ -836,12 +794,12 @@ async function createOpenid4vpAuthorizationRequest(options) {
|
|
|
836
794
|
}
|
|
837
795
|
|
|
838
796
|
// src/authorization-request/parse-authorization-request-params.ts
|
|
839
|
-
var
|
|
797
|
+
var import_oauth212 = require("@openid4vc/oauth2");
|
|
840
798
|
var import_utils9 = require("@openid4vc/utils");
|
|
841
799
|
var import_zod10 = __toESM(require("zod"));
|
|
842
800
|
|
|
843
801
|
// src/jar/z-jar-authorization-request.ts
|
|
844
|
-
var
|
|
802
|
+
var import_oauth211 = require("@openid4vc/oauth2");
|
|
845
803
|
var import_utils8 = require("@openid4vc/utils");
|
|
846
804
|
var import_zod9 = require("zod");
|
|
847
805
|
var zJarAuthorizationRequest = import_zod9.z.object({
|
|
@@ -853,13 +811,13 @@ var zJarAuthorizationRequest = import_zod9.z.object({
|
|
|
853
811
|
function validateJarRequestParams(options) {
|
|
854
812
|
const { jarRequestParams } = options;
|
|
855
813
|
if (jarRequestParams.request && jarRequestParams.request_uri) {
|
|
856
|
-
throw new
|
|
814
|
+
throw new import_oauth211.Oauth2ServerErrorResponseError({
|
|
857
815
|
error: "invalid_request_object",
|
|
858
816
|
error_description: "request and request_uri cannot both be present in a JAR request"
|
|
859
817
|
});
|
|
860
818
|
}
|
|
861
819
|
if (!jarRequestParams.request && !jarRequestParams.request_uri) {
|
|
862
|
-
throw new
|
|
820
|
+
throw new import_oauth211.Oauth2ServerErrorResponseError({
|
|
863
821
|
error: "invalid_request_object",
|
|
864
822
|
error_description: "request or request_uri must be present"
|
|
865
823
|
});
|
|
@@ -884,7 +842,7 @@ function parseOpenid4vpAuthorizationRequest(options) {
|
|
|
884
842
|
);
|
|
885
843
|
provided = "uri";
|
|
886
844
|
} else {
|
|
887
|
-
const decoded = (0,
|
|
845
|
+
const decoded = (0, import_oauth212.decodeJwt)({ jwt: authorizationRequest });
|
|
888
846
|
params = decoded.payload;
|
|
889
847
|
provided = "jwt";
|
|
890
848
|
}
|
|
@@ -922,7 +880,7 @@ var import_utils13 = require("@openid4vc/utils");
|
|
|
922
880
|
var import_zod14 = __toESM(require("zod"));
|
|
923
881
|
|
|
924
882
|
// src/fetch-client-metadata.ts
|
|
925
|
-
var
|
|
883
|
+
var import_oauth213 = require("@openid4vc/oauth2");
|
|
926
884
|
var import_utils10 = require("@openid4vc/utils");
|
|
927
885
|
async function fetchClientMetadata(options) {
|
|
928
886
|
const { fetch, clientMetadataUri } = options;
|
|
@@ -934,15 +892,15 @@ async function fetchClientMetadata(options) {
|
|
|
934
892
|
}
|
|
935
893
|
});
|
|
936
894
|
if (!response.ok) {
|
|
937
|
-
throw new
|
|
895
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
938
896
|
error_description: `Fetching client metadata from '${clientMetadataUri}' failed with status code '${response.status}'.`,
|
|
939
|
-
error:
|
|
897
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequestUri
|
|
940
898
|
});
|
|
941
899
|
}
|
|
942
900
|
if (!result || !result.success) {
|
|
943
|
-
throw new
|
|
901
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
944
902
|
error_description: `Parsing client metadata from '${clientMetadataUri}' failed.`,
|
|
945
|
-
error:
|
|
903
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequestObject
|
|
946
904
|
});
|
|
947
905
|
}
|
|
948
906
|
return result.data;
|
|
@@ -951,6 +909,68 @@ async function fetchClientMetadata(options) {
|
|
|
951
909
|
// src/jar/handle-jar-request/verify-jar-request.ts
|
|
952
910
|
var import_oauth217 = require("@openid4vc/oauth2");
|
|
953
911
|
|
|
912
|
+
// src/version.ts
|
|
913
|
+
var import_oauth214 = require("@openid4vc/oauth2");
|
|
914
|
+
function parseAuthorizationRequestVersion(request) {
|
|
915
|
+
const requirements = [];
|
|
916
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request) && (request.response_mode === "w3c_dc_api" || request.response_mode === "w3c_dc_api.jwt")) {
|
|
917
|
+
requirements.push(["<", 23]);
|
|
918
|
+
requirements.push([">=", 21]);
|
|
919
|
+
}
|
|
920
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request) && request.response_mode === "dc_api" || request.response_mode === "dc_api.jwt") {
|
|
921
|
+
requirements.push([">=", 23]);
|
|
922
|
+
}
|
|
923
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request) && (request.transaction_data || request.dcql_query)) {
|
|
924
|
+
requirements.push([">=", 23]);
|
|
925
|
+
}
|
|
926
|
+
if (request.dcql_query) {
|
|
927
|
+
requirements.push([">=", 22]);
|
|
928
|
+
}
|
|
929
|
+
if (request.transaction_data) {
|
|
930
|
+
requirements.push([">=", 22]);
|
|
931
|
+
}
|
|
932
|
+
if (request.client_id_scheme) {
|
|
933
|
+
requirements.push(["<", 22]);
|
|
934
|
+
}
|
|
935
|
+
if (request.client_id) {
|
|
936
|
+
const colonIndex = request.client_id.indexOf(":");
|
|
937
|
+
const schemePart = request.client_id.substring(0, colonIndex);
|
|
938
|
+
const parsedScheme = zClientIdScheme.safeParse(schemePart);
|
|
939
|
+
if (parsedScheme.success && parsedScheme.data !== "did" && parsedScheme.data !== "https") {
|
|
940
|
+
requirements.push([">=", 22]);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (!request.client_id) {
|
|
944
|
+
requirements.push([">=", 21]);
|
|
945
|
+
}
|
|
946
|
+
if (request.client_metadata_uri) {
|
|
947
|
+
requirements.push(["<", 21]);
|
|
948
|
+
}
|
|
949
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request)) {
|
|
950
|
+
requirements.push([">=", 21]);
|
|
951
|
+
}
|
|
952
|
+
if (request.request_uri_method || request.wallet_nonce) {
|
|
953
|
+
requirements.push([">=", 21]);
|
|
954
|
+
}
|
|
955
|
+
if (request.client_id_scheme === "verifier_attestation") {
|
|
956
|
+
requirements.push([">=", 20]);
|
|
957
|
+
}
|
|
958
|
+
if (request.client_id_scheme === "x509_san_dns" || request.client_id_scheme === "x509_san_uri") {
|
|
959
|
+
requirements.push([">=", 19]);
|
|
960
|
+
}
|
|
961
|
+
const lessThanVersions = requirements.filter(([operator]) => operator === "<").map(([_, version]) => version);
|
|
962
|
+
const greaterThanVersions = requirements.filter(([operator]) => operator === ">=").map(([_, version]) => version);
|
|
963
|
+
const highestPossibleVersion = lessThanVersions.length > 0 ? Math.max(Math.min(...lessThanVersions) - 1, 18) : 24;
|
|
964
|
+
const lowestRequiredVersion = greaterThanVersions.length > 0 ? Math.max(...greaterThanVersions) : 18;
|
|
965
|
+
if (lowestRequiredVersion > highestPossibleVersion) {
|
|
966
|
+
throw new import_oauth214.Oauth2ServerErrorResponseError({
|
|
967
|
+
error: import_oauth214.Oauth2ErrorCodes.InvalidRequest,
|
|
968
|
+
error_description: "Could not infer openid4vp version from the openid4vp request payload."
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
return highestPossibleVersion;
|
|
972
|
+
}
|
|
973
|
+
|
|
954
974
|
// src/jar/jar-request-object/fetch-jar-request-object.ts
|
|
955
975
|
var import_oauth215 = require("@openid4vc/oauth2");
|
|
956
976
|
var import_utils11 = require("@openid4vc/utils");
|
|
@@ -999,7 +1019,7 @@ async function verifyJarRequest(options) {
|
|
|
999
1019
|
const { callbacks, wallet = {} } = options;
|
|
1000
1020
|
const jarRequestParams = validateJarRequestParams(options);
|
|
1001
1021
|
const sendBy = jarRequestParams.request ? "value" : "reference";
|
|
1002
|
-
const clientIdentifierScheme = jarRequestParams.client_id ? zClientIdScheme.
|
|
1022
|
+
const clientIdentifierScheme = jarRequestParams.client_id ? zClientIdScheme.safeParse(jarRequestParams.client_id.split(":")[0]).data : "web-origin";
|
|
1003
1023
|
const method = jarRequestParams.request_uri_method ?? "GET";
|
|
1004
1024
|
if (method !== "GET" && method !== "POST") {
|
|
1005
1025
|
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
@@ -1300,7 +1320,7 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1300
1320
|
const { authorizationRequestPayload, jarm, callbacks } = options;
|
|
1301
1321
|
const authorizationResponsePayload = {
|
|
1302
1322
|
...options.authorizationResponsePayload,
|
|
1303
|
-
|
|
1323
|
+
state: authorizationRequestPayload.state
|
|
1304
1324
|
};
|
|
1305
1325
|
if (authorizationRequestPayload.response_mode && isJarmResponseMode(authorizationRequestPayload.response_mode) && !jarm) {
|
|
1306
1326
|
throw new import_oauth222.Oauth2Error(
|
|
@@ -1484,7 +1504,7 @@ function parseDcqlVpToken(vpToken) {
|
|
|
1484
1504
|
// src/authorization-response/validate-authorization-response.ts
|
|
1485
1505
|
function validateOpenid4vpAuthorizationResponsePayload(options) {
|
|
1486
1506
|
const { authorizationRequestPayload, authorizationResponsePayload } = options;
|
|
1487
|
-
if (
|
|
1507
|
+
if (authorizationRequestPayload.state && authorizationRequestPayload.state !== authorizationResponsePayload.state) {
|
|
1488
1508
|
throw new import_oauth225.Oauth2Error("OpenId4Vp Authorization Response state mismatch.");
|
|
1489
1509
|
}
|
|
1490
1510
|
if (authorizationResponsePayload.id_token) {
|
|
@@ -1496,7 +1516,7 @@ function validateOpenid4vpAuthorizationResponsePayload(options) {
|
|
|
1496
1516
|
}
|
|
1497
1517
|
return {
|
|
1498
1518
|
type: "pex",
|
|
1499
|
-
pex:
|
|
1519
|
+
pex: authorizationRequestPayload.scope ? {
|
|
1500
1520
|
scope: authorizationRequestPayload.scope,
|
|
1501
1521
|
presentationSubmission: authorizationResponsePayload.presentation_submission,
|
|
1502
1522
|
presentations: parsePexVpToken(authorizationResponsePayload.vp_token)
|
|
@@ -1511,7 +1531,7 @@ function validateOpenid4vpAuthorizationResponsePayload(options) {
|
|
|
1511
1531
|
const presentations = parseDcqlVpToken(authorizationResponsePayload.vp_token);
|
|
1512
1532
|
return {
|
|
1513
1533
|
type: "dcql",
|
|
1514
|
-
dcql:
|
|
1534
|
+
dcql: authorizationRequestPayload.scope ? {
|
|
1515
1535
|
scope: authorizationRequestPayload.scope,
|
|
1516
1536
|
presentations
|
|
1517
1537
|
} : {
|
|
@@ -1605,13 +1625,18 @@ async function parseJarmAuthorizationResponse(options) {
|
|
|
1605
1625
|
// src/authorization-response/parse-authorization-response.ts
|
|
1606
1626
|
async function parseOpenid4vpAuthorizationResponse(options) {
|
|
1607
1627
|
const { authorizationResponse, callbacks, authorizationRequestPayload, origin } = options;
|
|
1608
|
-
const expectedClientId = getOpenid4vpClientId({
|
|
1628
|
+
const expectedClientId = getOpenid4vpClientId({
|
|
1629
|
+
origin,
|
|
1630
|
+
authorizationRequestPayload
|
|
1631
|
+
});
|
|
1609
1632
|
if (authorizationResponse.response) {
|
|
1610
1633
|
return parseJarmAuthorizationResponse({
|
|
1611
1634
|
jarmResponseJwt: authorizationResponse.response,
|
|
1612
1635
|
callbacks,
|
|
1613
1636
|
authorizationRequestPayload,
|
|
1614
|
-
|
|
1637
|
+
// If client_id_scheme was provided we should use the legacy (unprefixed) client id scheme
|
|
1638
|
+
// TODO: allow both versions, in case of e.g. did:
|
|
1639
|
+
expectedClientId: expectedClientId.legacyClientId ?? expectedClientId.clientId
|
|
1615
1640
|
});
|
|
1616
1641
|
}
|
|
1617
1642
|
const authorizationResponsePayload = parseOpenid4VpAuthorizationResponsePayload(authorizationResponse);
|