@openid4vc/openid4vp 0.3.0-alpha-20250707100752 → 0.3.0-alpha-20250707121837
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 +8237 -89
- package/dist/index.d.ts +8237 -89
- package/dist/index.js +489 -306
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +362 -178
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
validateOpenid4vpAuthorizationRequestPayload: () => validateOpenid4vpAuthorizationRequestPayload,
|
|
51
51
|
validateOpenid4vpAuthorizationResponsePayload: () => validateOpenid4vpAuthorizationResponsePayload,
|
|
52
52
|
verifyJarmAuthorizationResponse: () => verifyJarmAuthorizationResponse,
|
|
53
|
-
|
|
53
|
+
zClientIdPrefix: () => zClientIdPrefix,
|
|
54
54
|
zClientMetadata: () => zClientMetadata,
|
|
55
55
|
zCredentialFormat: () => zCredentialFormat,
|
|
56
56
|
zJarmClientMetadata: () => zJarmClientMetadata,
|
|
@@ -61,8 +61,9 @@ __export(index_exports, {
|
|
|
61
61
|
});
|
|
62
62
|
module.exports = __toCommonJS(index_exports);
|
|
63
63
|
|
|
64
|
-
// src/client-identifier-
|
|
64
|
+
// src/client-identifier-prefix/parse-client-identifier-prefix.ts
|
|
65
65
|
var import_oauth23 = require("@openid4vc/oauth2");
|
|
66
|
+
var import_oauth24 = require("@openid4vc/oauth2");
|
|
66
67
|
var import_utils5 = require("@openid4vc/utils");
|
|
67
68
|
|
|
68
69
|
// src/authorization-request/z-authorization-request-dc-api.ts
|
|
@@ -117,7 +118,7 @@ var zJarmClientMetadataParsed = zJarmClientMetadata.transform((client_metadata)
|
|
|
117
118
|
type: "sign_encrypt",
|
|
118
119
|
client_metadata: {
|
|
119
120
|
...SignEncrypt.data,
|
|
120
|
-
authorization_encrypted_response_enc: client_metadata.authorization_encrypted_response_enc
|
|
121
|
+
authorization_encrypted_response_enc: client_metadata.authorization_encrypted_response_enc
|
|
121
122
|
}
|
|
122
123
|
};
|
|
123
124
|
}
|
|
@@ -127,7 +128,7 @@ var zJarmClientMetadataParsed = zJarmClientMetadata.transform((client_metadata)
|
|
|
127
128
|
type: "encrypt",
|
|
128
129
|
client_metadata: {
|
|
129
130
|
...encryptOnly.data,
|
|
130
|
-
authorization_encrypted_response_enc: parsedClientMeta.authorization_encrypted_response_enc
|
|
131
|
+
authorization_encrypted_response_enc: parsedClientMeta.authorization_encrypted_response_enc
|
|
131
132
|
}
|
|
132
133
|
};
|
|
133
134
|
}
|
|
@@ -137,7 +138,7 @@ var zJarmClientMetadataParsed = zJarmClientMetadata.transform((client_metadata)
|
|
|
137
138
|
type: "sign",
|
|
138
139
|
client_metadata: {
|
|
139
140
|
...signOnly.data,
|
|
140
|
-
authorization_signed_response_alg: parsedClientMeta.authorization_signed_response_alg
|
|
141
|
+
authorization_signed_response_alg: parsedClientMeta.authorization_signed_response_alg
|
|
141
142
|
}
|
|
142
143
|
};
|
|
143
144
|
}
|
|
@@ -146,7 +147,36 @@ var zJarmClientMetadataParsed = zJarmClientMetadata.transform((client_metadata)
|
|
|
146
147
|
|
|
147
148
|
// src/models/z-vp-formats-supported.ts
|
|
148
149
|
var import_zod2 = require("zod");
|
|
149
|
-
var zVpFormatsSupported = import_zod2.z.
|
|
150
|
+
var zVpFormatsSupported = import_zod2.z.object({
|
|
151
|
+
"dc+sd-jwt": import_zod2.z.optional(
|
|
152
|
+
import_zod2.z.object({
|
|
153
|
+
"sd-jwt_alg_values": import_zod2.z.optional(import_zod2.z.array(import_zod2.z.string()).nonempty()),
|
|
154
|
+
"kb-jwt_alg_values": import_zod2.z.optional(import_zod2.z.array(import_zod2.z.string()).nonempty())
|
|
155
|
+
}).passthrough()
|
|
156
|
+
),
|
|
157
|
+
jwt_vc_json: import_zod2.z.optional(
|
|
158
|
+
import_zod2.z.object({
|
|
159
|
+
alg_values: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.string()).nonempty())
|
|
160
|
+
}).passthrough()
|
|
161
|
+
),
|
|
162
|
+
ldp_vc: import_zod2.z.optional(
|
|
163
|
+
import_zod2.z.object({
|
|
164
|
+
proof_type_values: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.string()).nonempty()),
|
|
165
|
+
cryptosuite_values: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.string()).nonempty())
|
|
166
|
+
}).passthrough()
|
|
167
|
+
),
|
|
168
|
+
mso_mdoc: import_zod2.z.optional(
|
|
169
|
+
import_zod2.z.object({
|
|
170
|
+
// Draft 27
|
|
171
|
+
issuer_signed_alg_values: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.number()).nonempty()),
|
|
172
|
+
device_signed_alg_values: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.number()).nonempty()),
|
|
173
|
+
// Draft 28+
|
|
174
|
+
issuerauth_alg_values: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.number()).nonempty()),
|
|
175
|
+
deviceauth_alg_values: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.number()).nonempty())
|
|
176
|
+
}).passthrough()
|
|
177
|
+
)
|
|
178
|
+
}).passthrough().catchall(import_zod2.z.object({}).passthrough());
|
|
179
|
+
var zLegacyVpFormats = import_zod2.z.record(
|
|
150
180
|
import_zod2.z.string(),
|
|
151
181
|
import_zod2.z.object({
|
|
152
182
|
alg_values_supported: import_zod2.z.optional(import_zod2.z.array(import_zod2.z.string()))
|
|
@@ -158,7 +188,12 @@ var zClientMetadata = import_zod3.z.object({
|
|
|
158
188
|
// Up until draft 22
|
|
159
189
|
jwks_uri: import_zod3.z.string().url().optional(),
|
|
160
190
|
jwks: import_zod3.z.optional(import_oauth22.zJwkSet),
|
|
161
|
-
|
|
191
|
+
// Up until draft 26
|
|
192
|
+
vp_formats: import_zod3.z.optional(zLegacyVpFormats),
|
|
193
|
+
// From draft 27
|
|
194
|
+
vp_formats_supported: import_zod3.z.optional(zVpFormatsSupported),
|
|
195
|
+
// From draft 28
|
|
196
|
+
encrypted_response_enc_values_supported: import_zod3.z.optional(import_zod3.z.array(import_zod3.z.string())),
|
|
162
197
|
...zJarmClientMetadata.shape,
|
|
163
198
|
logo_uri: import_utils2.zHttpsUrl.optional(),
|
|
164
199
|
client_name: import_zod3.z.string().optional()
|
|
@@ -200,9 +235,11 @@ var zOpenid4vpAuthorizationRequest = import_zod5.z.object({
|
|
|
200
235
|
"did",
|
|
201
236
|
"verifier_attestation",
|
|
202
237
|
"x509_san_dns",
|
|
203
|
-
"x509_san_uri"
|
|
238
|
+
"x509_san_uri",
|
|
239
|
+
"x509_hash"
|
|
204
240
|
]).optional(),
|
|
205
|
-
verifier_attestations: zVerifierAttestations.optional()
|
|
241
|
+
verifier_attestations: zVerifierAttestations.optional(),
|
|
242
|
+
verifier_info: zVerifierAttestations.optional()
|
|
206
243
|
}).passthrough();
|
|
207
244
|
var zOpenid4vpAuthorizationRequestFromUriParams = import_zod5.z.string().url().transform((url) => Object.fromEntries(new import_utils3.URL(url).searchParams)).pipe(
|
|
208
245
|
import_zod5.z.object({
|
|
@@ -210,7 +247,8 @@ var zOpenid4vpAuthorizationRequestFromUriParams = import_zod5.z.string().url().t
|
|
|
210
247
|
client_metadata: import_utils3.zStringToJson.optional(),
|
|
211
248
|
dcql_query: import_utils3.zStringToJson.optional(),
|
|
212
249
|
transaction_data: import_utils3.zStringToJson.optional(),
|
|
213
|
-
verifier_attestations: import_utils3.zStringToJson.optional()
|
|
250
|
+
verifier_attestations: import_utils3.zStringToJson.optional(),
|
|
251
|
+
verifier_info: import_utils3.zStringToJson.optional()
|
|
214
252
|
}).passthrough()
|
|
215
253
|
);
|
|
216
254
|
|
|
@@ -225,7 +263,8 @@ var zOpenid4vpAuthorizationRequestDcApi = zOpenid4vpAuthorizationRequest.pick({
|
|
|
225
263
|
dcql_query: true,
|
|
226
264
|
trust_chain: true,
|
|
227
265
|
state: true,
|
|
228
|
-
verifier_attestations: true
|
|
266
|
+
verifier_attestations: true,
|
|
267
|
+
verifier_info: true
|
|
229
268
|
}).extend({
|
|
230
269
|
client_id: import_zod6.z.optional(import_zod6.z.string()),
|
|
231
270
|
expected_origins: import_zod6.z.array(import_zod6.z.string()).optional(),
|
|
@@ -242,31 +281,55 @@ function isOpenid4vpAuthorizationRequestDcApi(request) {
|
|
|
242
281
|
return isOpenid4vpResponseModeDcApi(request.response_mode);
|
|
243
282
|
}
|
|
244
283
|
|
|
245
|
-
// src/client-identifier-
|
|
284
|
+
// src/client-identifier-prefix/z-client-id-prefix.ts
|
|
246
285
|
var import_utils4 = require("@openid4vc/utils");
|
|
247
286
|
var import_zod7 = require("zod");
|
|
248
|
-
var
|
|
287
|
+
var zClientIdPrefix = import_zod7.z.enum([
|
|
249
288
|
"pre-registered",
|
|
250
289
|
"redirect_uri",
|
|
251
|
-
"https",
|
|
252
290
|
"verifier_attestation",
|
|
291
|
+
"https",
|
|
292
|
+
// pre draft 26
|
|
293
|
+
"openid_federation",
|
|
294
|
+
// from draft 26
|
|
253
295
|
"did",
|
|
254
|
-
|
|
296
|
+
// pre draft 26
|
|
297
|
+
"decentralized_identifier",
|
|
298
|
+
// from draft 26
|
|
255
299
|
"x509_san_uri",
|
|
300
|
+
// pre-draft 25
|
|
301
|
+
"x509_hash",
|
|
302
|
+
// from draft 25
|
|
303
|
+
"x509_san_dns",
|
|
304
|
+
"origin",
|
|
305
|
+
// from draft 25
|
|
256
306
|
"web-origin"
|
|
307
|
+
// pre-draft 25
|
|
257
308
|
]);
|
|
258
|
-
var
|
|
309
|
+
var zUniformClientIdPrefix = zClientIdPrefix.exclude(["did", "https", "web-origin"]);
|
|
310
|
+
var zClientIdToClientIdPrefixAndIdentifier = import_zod7.z.union(
|
|
259
311
|
[
|
|
260
312
|
import_zod7.z.string({ message: "client_id MUST be a string" }).includes(":").transform((clientId) => {
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
313
|
+
const colonIndex = clientId.indexOf(":");
|
|
314
|
+
const clientIdPrefix = clientId.slice(0, colonIndex);
|
|
315
|
+
const clientIdIdentifier = clientId.slice(colonIndex + 1);
|
|
316
|
+
if (clientIdPrefix === "http" && (0, import_utils4.getGlobalConfig)().allowInsecureUrls) {
|
|
317
|
+
return ["https", clientId];
|
|
318
|
+
}
|
|
319
|
+
if (clientIdPrefix === "did" || clientIdPrefix === "http" || clientIdPrefix === "https") {
|
|
320
|
+
return [clientIdPrefix, clientId];
|
|
321
|
+
}
|
|
322
|
+
return [clientIdPrefix, clientIdIdentifier];
|
|
323
|
+
}).pipe(import_zod7.z.tuple([zClientIdPrefix.exclude(["pre-registered"]), import_zod7.z.string()])),
|
|
324
|
+
import_zod7.z.string().refine((clientId) => clientId.includes(":") === false).transform((clientId) => ["pre-registered", clientId])
|
|
265
325
|
],
|
|
266
326
|
{
|
|
267
|
-
message: `client_id must either start with a known prefix followed by ':' or contain no ':'. Known prefixes are ${
|
|
327
|
+
message: `client_id must either start with a known prefix followed by ':' or contain no ':'. Known prefixes are ${zClientIdPrefix.exclude(["pre-registered"]).options.join(", ")}`
|
|
268
328
|
}
|
|
269
329
|
);
|
|
330
|
+
var zClientIdPrefixToUniform = zClientIdPrefix.transform(
|
|
331
|
+
(prefix) => prefix === "did" ? "decentralized_identifier" : prefix === "https" ? "openid_federation" : prefix === "web-origin" ? "origin" : prefix
|
|
332
|
+
);
|
|
270
333
|
var zLegacyClientIdScheme = import_zod7.z.enum([
|
|
271
334
|
"pre-registered",
|
|
272
335
|
"redirect_uri",
|
|
@@ -276,10 +339,15 @@ var zLegacyClientIdScheme = import_zod7.z.enum([
|
|
|
276
339
|
"x509_san_dns",
|
|
277
340
|
"x509_san_uri"
|
|
278
341
|
]);
|
|
279
|
-
var
|
|
342
|
+
var zLegacyClientIdSchemeToClientIdPrefix = zLegacyClientIdScheme.optional().default("pre-registered").transform(
|
|
343
|
+
(clientIdScheme) => clientIdScheme === "entity_id" ? "openid_federation" : clientIdScheme === "did" ? "decentralized_identifier" : clientIdScheme
|
|
344
|
+
);
|
|
280
345
|
|
|
281
|
-
// src/client-identifier-
|
|
346
|
+
// src/client-identifier-prefix/parse-client-identifier-prefix.ts
|
|
282
347
|
function getOpenid4vpClientId(options) {
|
|
348
|
+
const original = {
|
|
349
|
+
clientId: options.clientId
|
|
350
|
+
};
|
|
283
351
|
if (isOpenid4vpResponseModeDcApi(options.responseMode)) {
|
|
284
352
|
if (!options.clientId) {
|
|
285
353
|
if (!options.origin) {
|
|
@@ -289,20 +357,37 @@ function getOpenid4vpClientId(options) {
|
|
|
289
357
|
});
|
|
290
358
|
}
|
|
291
359
|
return {
|
|
292
|
-
|
|
293
|
-
|
|
360
|
+
clientIdPrefix: "origin",
|
|
361
|
+
effectiveClientIdPrefix: "origin",
|
|
362
|
+
clientIdIdentifier: options.origin,
|
|
363
|
+
// FIXME: draft 24 uses web-origin, draft 25+ uses origin
|
|
364
|
+
// But it's not really possible to know which one to use as the
|
|
365
|
+
// 'effective' client id. Defaulting to origin: since that's newer
|
|
366
|
+
effectiveClientId: `origin:${options.origin}`,
|
|
367
|
+
original
|
|
294
368
|
};
|
|
295
369
|
}
|
|
296
|
-
const
|
|
297
|
-
if (!
|
|
370
|
+
const parsedClientIdPrefixAndIdentifier2 = zClientIdToClientIdPrefixAndIdentifier.safeParse(options.clientId);
|
|
371
|
+
if (!parsedClientIdPrefixAndIdentifier2.success) {
|
|
372
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
373
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
374
|
+
error_description: `Failed to parse client identifier. Unsupported client_id '${options.clientId}'.`
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
const [clientIdScheme2, clientIdIdentifier2] = parsedClientIdPrefixAndIdentifier2.data;
|
|
378
|
+
const uniformClientIdScheme2 = zClientIdPrefixToUniform.safeParse(clientIdScheme2);
|
|
379
|
+
if (!uniformClientIdScheme2.success) {
|
|
298
380
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
299
381
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
300
382
|
error_description: `Failed to parse client identifier. Unsupported client_id '${options.clientId}'.`
|
|
301
383
|
});
|
|
302
384
|
}
|
|
303
385
|
return {
|
|
304
|
-
|
|
305
|
-
|
|
386
|
+
effectiveClientId: options.clientId,
|
|
387
|
+
effectiveClientIdPrefix: clientIdScheme2,
|
|
388
|
+
original,
|
|
389
|
+
clientIdPrefix: uniformClientIdScheme2.data,
|
|
390
|
+
clientIdIdentifier: clientIdIdentifier2
|
|
306
391
|
};
|
|
307
392
|
}
|
|
308
393
|
if (!options.clientId) {
|
|
@@ -312,62 +397,75 @@ function getOpenid4vpClientId(options) {
|
|
|
312
397
|
});
|
|
313
398
|
}
|
|
314
399
|
if (options.legacyClientIdScheme) {
|
|
315
|
-
const
|
|
316
|
-
if (!
|
|
400
|
+
const parsedClientIdPrefix = zLegacyClientIdSchemeToClientIdPrefix.safeParse(options.legacyClientIdScheme);
|
|
401
|
+
if (!parsedClientIdPrefix.success) {
|
|
317
402
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
318
403
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
319
404
|
error_description: `Failed to parse client identifier. Unsupported client_id_scheme value '${options.legacyClientIdScheme}'.`
|
|
320
405
|
});
|
|
321
406
|
}
|
|
322
|
-
const
|
|
407
|
+
const clientIdPrefix = parsedClientIdPrefix.data;
|
|
323
408
|
return {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
409
|
+
effectiveClientId: options.clientId,
|
|
410
|
+
clientIdIdentifier: options.clientId,
|
|
411
|
+
clientIdPrefix,
|
|
412
|
+
effectiveClientIdPrefix: options.legacyClientIdScheme ?? "pre-registered",
|
|
413
|
+
original: {
|
|
414
|
+
...original,
|
|
415
|
+
clientIdScheme: options.legacyClientIdScheme
|
|
416
|
+
}
|
|
327
417
|
};
|
|
328
418
|
}
|
|
329
|
-
const
|
|
330
|
-
if (!
|
|
419
|
+
const parsedClientIdPrefixAndIdentifier = zClientIdToClientIdPrefixAndIdentifier.safeParse(options.clientId);
|
|
420
|
+
if (!parsedClientIdPrefixAndIdentifier.success) {
|
|
421
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
422
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
423
|
+
error_description: `Failed to parse client identifier. Unsupported client_id '${options.clientId}'.`
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
const [clientIdScheme, clientIdIdentifier] = parsedClientIdPrefixAndIdentifier.data;
|
|
427
|
+
const uniformClientIdScheme = zClientIdPrefixToUniform.safeParse(clientIdScheme);
|
|
428
|
+
if (!uniformClientIdScheme.success) {
|
|
331
429
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
332
430
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
333
431
|
error_description: `Failed to parse client identifier. Unsupported client_id '${options.clientId}'.`
|
|
334
432
|
});
|
|
335
433
|
}
|
|
336
434
|
return {
|
|
337
|
-
|
|
338
|
-
|
|
435
|
+
effectiveClientId: options.clientId,
|
|
436
|
+
clientIdPrefix: uniformClientIdScheme.data,
|
|
437
|
+
effectiveClientIdPrefix: clientIdScheme,
|
|
438
|
+
clientIdIdentifier,
|
|
439
|
+
original
|
|
339
440
|
};
|
|
340
441
|
}
|
|
341
|
-
function validateOpenid4vpClientId(options, parserConfig) {
|
|
442
|
+
async function validateOpenid4vpClientId(options, parserConfig) {
|
|
342
443
|
const { authorizationRequestPayload, jar, origin } = options;
|
|
343
444
|
const parserConfigWithDefaults = {
|
|
344
|
-
supportedSchemes: parserConfig?.supportedSchemes || Object.values(
|
|
445
|
+
supportedSchemes: parserConfig?.supportedSchemes || Object.values(zClientIdPrefix.options)
|
|
345
446
|
};
|
|
346
|
-
const {
|
|
447
|
+
const { clientIdIdentifier, clientIdPrefix, effectiveClientId, original } = getOpenid4vpClientId({
|
|
347
448
|
clientId: authorizationRequestPayload.client_id,
|
|
348
449
|
legacyClientIdScheme: authorizationRequestPayload.client_id_scheme,
|
|
349
450
|
responseMode: authorizationRequestPayload.response_mode,
|
|
350
451
|
origin
|
|
351
452
|
});
|
|
352
|
-
if (
|
|
453
|
+
if (clientIdPrefix === "pre-registered") {
|
|
353
454
|
return {
|
|
354
|
-
|
|
355
|
-
identifier:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
clientMetadata: authorizationRequestPayload.client_metadata
|
|
455
|
+
prefix: "pre-registered",
|
|
456
|
+
identifier: clientIdIdentifier,
|
|
457
|
+
effective: effectiveClientId,
|
|
458
|
+
original
|
|
359
459
|
};
|
|
360
460
|
}
|
|
361
|
-
|
|
362
|
-
const identifierPart = clientId.substring(colonIndex + 1);
|
|
363
|
-
if (!parserConfigWithDefaults.supportedSchemes.includes(clientIdScheme)) {
|
|
461
|
+
if (!parserConfigWithDefaults.supportedSchemes.includes(clientIdPrefix)) {
|
|
364
462
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
365
463
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
366
|
-
error_description: `Unsupported client identifier scheme. ${
|
|
464
|
+
error_description: `Unsupported client identifier scheme. ${clientIdPrefix} is not supported.`
|
|
367
465
|
});
|
|
368
466
|
}
|
|
369
|
-
if (
|
|
370
|
-
if (!import_utils5.zHttpsUrl.safeParse(
|
|
467
|
+
if (clientIdPrefix === "openid_federation") {
|
|
468
|
+
if (!import_utils5.zHttpsUrl.safeParse(clientIdIdentifier).success) {
|
|
371
469
|
throw new import_oauth23.Oauth2ServerErrorResponseError(
|
|
372
470
|
{
|
|
373
471
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
@@ -391,14 +489,14 @@ function validateOpenid4vpClientId(options, parserConfig) {
|
|
|
391
489
|
});
|
|
392
490
|
}
|
|
393
491
|
return {
|
|
394
|
-
|
|
395
|
-
identifier:
|
|
396
|
-
|
|
397
|
-
|
|
492
|
+
prefix: "openid_federation",
|
|
493
|
+
identifier: clientIdIdentifier,
|
|
494
|
+
effective: effectiveClientId,
|
|
495
|
+
original,
|
|
398
496
|
trustChain: authorizationRequestPayload.trust_chain
|
|
399
497
|
};
|
|
400
498
|
}
|
|
401
|
-
if (
|
|
499
|
+
if (clientIdPrefix === "redirect_uri") {
|
|
402
500
|
if (jar) {
|
|
403
501
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
404
502
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
@@ -412,14 +510,15 @@ function validateOpenid4vpClientId(options, parserConfig) {
|
|
|
412
510
|
});
|
|
413
511
|
}
|
|
414
512
|
return {
|
|
415
|
-
|
|
416
|
-
identifier:
|
|
417
|
-
|
|
418
|
-
|
|
513
|
+
prefix: clientIdPrefix,
|
|
514
|
+
identifier: clientIdIdentifier,
|
|
515
|
+
effective: effectiveClientId,
|
|
516
|
+
original,
|
|
517
|
+
clientMetadata: authorizationRequestPayload.client_metadata,
|
|
419
518
|
redirectUri: authorizationRequestPayload.redirect_uri ?? authorizationRequestPayload.response_uri
|
|
420
519
|
};
|
|
421
520
|
}
|
|
422
|
-
if (
|
|
521
|
+
if (clientIdPrefix === "decentralized_identifier") {
|
|
423
522
|
if (!jar) {
|
|
424
523
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
425
524
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
@@ -432,113 +531,115 @@ function validateOpenid4vpClientId(options, parserConfig) {
|
|
|
432
531
|
error_description: "Something went wrong. The JWT signer method is not did but the client identifier scheme is did."
|
|
433
532
|
});
|
|
434
533
|
}
|
|
435
|
-
if (!
|
|
534
|
+
if (!clientIdIdentifier.startsWith("did:")) {
|
|
436
535
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
437
536
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
438
|
-
error_description: "Invalid client identifier. Client identifier must start with 'did:'"
|
|
537
|
+
error_description: "Invalid client identifier. Client id identifier must start with 'did:'"
|
|
439
538
|
});
|
|
440
539
|
}
|
|
441
540
|
const [did] = jar.signer.didUrl.split("#");
|
|
442
|
-
if (
|
|
541
|
+
if (clientIdIdentifier !== did) {
|
|
443
542
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
444
543
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
445
|
-
error_description:
|
|
544
|
+
error_description: `With client identifier scheme '${clientIdPrefix}' the JAR request must be signed by the same DID as the client identifier.`
|
|
446
545
|
});
|
|
447
546
|
}
|
|
448
547
|
return {
|
|
449
|
-
|
|
450
|
-
identifier:
|
|
451
|
-
|
|
452
|
-
|
|
548
|
+
prefix: "decentralized_identifier",
|
|
549
|
+
identifier: clientIdIdentifier,
|
|
550
|
+
effective: effectiveClientId,
|
|
551
|
+
original,
|
|
552
|
+
clientMetadata: authorizationRequestPayload.client_metadata,
|
|
453
553
|
didUrl: jar.signer.didUrl
|
|
454
554
|
};
|
|
455
555
|
}
|
|
456
|
-
if (
|
|
556
|
+
if (clientIdPrefix === "x509_san_dns" || clientIdPrefix === "x509_san_uri" || clientIdPrefix === "x509_hash") {
|
|
457
557
|
if (!jar) {
|
|
458
558
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
459
559
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
460
|
-
error_description:
|
|
560
|
+
error_description: `Using client identifier scheme '${clientIdPrefix}' requires a signed JAR request.`
|
|
461
561
|
});
|
|
462
562
|
}
|
|
463
563
|
if (jar.signer.method !== "x5c") {
|
|
464
564
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
465
565
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
466
|
-
error_description:
|
|
566
|
+
error_description: `Something went wrong. The JWT signer method is not x5c but the client identifier scheme is '${clientIdPrefix}'`
|
|
467
567
|
});
|
|
468
568
|
}
|
|
469
|
-
if (
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
{
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
569
|
+
if (!options.callbacks.getX509CertificateMetadata) {
|
|
570
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError(
|
|
571
|
+
{
|
|
572
|
+
error: import_oauth23.Oauth2ErrorCodes.ServerError
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
internalMessage: `Missing required 'getX509CertificateMetadata' callback for verification of '${clientIdPrefix}' client id scheme`
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
if (clientIdPrefix === "x509_san_dns") {
|
|
480
580
|
const { sanDnsNames } = options.callbacks.getX509CertificateMetadata(jar.signer.x5c[0]);
|
|
481
|
-
if (!sanDnsNames.includes(
|
|
581
|
+
if (!sanDnsNames.includes(clientIdIdentifier)) {
|
|
482
582
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
483
583
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
484
|
-
error_description: `Invalid client identifier. One of the leaf certificates san dns names [${sanDnsNames.join(", ")}] must match the client identifier '${
|
|
584
|
+
error_description: `Invalid client identifier. One of the leaf certificates san dns names [${sanDnsNames.join(", ")}] must match the client identifier '${clientIdIdentifier}'. `
|
|
485
585
|
});
|
|
486
586
|
}
|
|
487
587
|
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
488
588
|
const uri = authorizationRequestPayload.redirect_uri ?? authorizationRequestPayload.response_uri;
|
|
489
|
-
if (!uri || new import_utils5.URL(uri).hostname !==
|
|
589
|
+
if (!uri || new import_utils5.URL(uri).hostname !== clientIdIdentifier) {
|
|
490
590
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
491
591
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
492
592
|
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."
|
|
493
593
|
});
|
|
494
594
|
}
|
|
495
595
|
}
|
|
496
|
-
} else if (
|
|
497
|
-
if (!options.callbacks.getX509CertificateMetadata) {
|
|
498
|
-
throw new import_oauth23.Oauth2ServerErrorResponseError(
|
|
499
|
-
{
|
|
500
|
-
error: import_oauth23.Oauth2ErrorCodes.ServerError
|
|
501
|
-
},
|
|
502
|
-
{
|
|
503
|
-
internalMessage: "Missing required 'getX509CertificateMetadata' callback for verification of 'x509_san_uri' client id scheme"
|
|
504
|
-
}
|
|
505
|
-
);
|
|
506
|
-
}
|
|
596
|
+
} else if (clientIdPrefix === "x509_san_uri") {
|
|
507
597
|
const { sanUriNames } = options.callbacks.getX509CertificateMetadata(jar.signer.x5c[0]);
|
|
508
|
-
if (!sanUriNames.includes(
|
|
598
|
+
if (!sanUriNames.includes(clientIdIdentifier)) {
|
|
509
599
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
510
600
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
511
|
-
error_description: `Invalid client identifier. One of the leaf certificates san uri names [${sanUriNames.join(", ")}] must match the client identifier '${
|
|
601
|
+
error_description: `Invalid client identifier. One of the leaf certificates san uri names [${sanUriNames.join(", ")}] must match the client identifier '${clientIdIdentifier}'.`
|
|
512
602
|
});
|
|
513
603
|
}
|
|
514
604
|
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
515
605
|
const uri = authorizationRequestPayload.redirect_uri || authorizationRequestPayload.response_uri;
|
|
516
|
-
if (!uri || uri !==
|
|
606
|
+
if (!uri || uri !== clientIdIdentifier) {
|
|
517
607
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
518
608
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
519
609
|
error_description: "The redirect_uri value MUST match the Client Identifier without the prefix x509_san_uri"
|
|
520
610
|
});
|
|
521
611
|
}
|
|
522
612
|
}
|
|
613
|
+
} else if (clientIdPrefix === "x509_hash") {
|
|
614
|
+
const x509Hash = (0, import_utils5.encodeToBase64Url)(
|
|
615
|
+
await options.callbacks.hash((0, import_utils5.decodeBase64)(jar.signer.x5c[0]), import_oauth24.HashAlgorithm.Sha256)
|
|
616
|
+
);
|
|
617
|
+
if (x509Hash !== clientIdIdentifier) {
|
|
618
|
+
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
619
|
+
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
620
|
+
error_description: `Invalid client identifier. Expected the base64url encoded sha-256 hash of the leaf x5c certificate ('${x509Hash}') to match the client identifier '${clientIdIdentifier}'.`
|
|
621
|
+
});
|
|
622
|
+
}
|
|
523
623
|
}
|
|
524
624
|
return {
|
|
525
|
-
|
|
526
|
-
identifier:
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
x5c: jar.signer.x5c
|
|
625
|
+
prefix: clientIdPrefix,
|
|
626
|
+
identifier: clientIdIdentifier,
|
|
627
|
+
effective: effectiveClientId,
|
|
628
|
+
original,
|
|
629
|
+
x5c: jar.signer.x5c,
|
|
630
|
+
clientMetadata: authorizationRequestPayload.client_metadata
|
|
530
631
|
};
|
|
531
632
|
}
|
|
532
|
-
if (
|
|
633
|
+
if (clientIdPrefix === "origin") {
|
|
533
634
|
return {
|
|
534
|
-
|
|
535
|
-
identifier:
|
|
536
|
-
|
|
537
|
-
|
|
635
|
+
prefix: clientIdPrefix,
|
|
636
|
+
identifier: clientIdIdentifier,
|
|
637
|
+
effective: effectiveClientId,
|
|
638
|
+
original,
|
|
538
639
|
clientMetadata: authorizationRequestPayload.client_metadata
|
|
539
640
|
};
|
|
540
641
|
}
|
|
541
|
-
if (
|
|
642
|
+
if (clientIdPrefix === "verifier_attestation") {
|
|
542
643
|
if (!jar) {
|
|
543
644
|
throw new import_oauth23.Oauth2ServerErrorResponseError({
|
|
544
645
|
error: import_oauth23.Oauth2ErrorCodes.InvalidRequest,
|
|
@@ -547,49 +648,53 @@ function validateOpenid4vpClientId(options, parserConfig) {
|
|
|
547
648
|
}
|
|
548
649
|
}
|
|
549
650
|
return {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
651
|
+
prefix: clientIdPrefix,
|
|
652
|
+
clientMetadata: authorizationRequestPayload.client_metadata,
|
|
653
|
+
identifier: clientIdIdentifier,
|
|
654
|
+
effective: effectiveClientId,
|
|
655
|
+
original
|
|
554
656
|
};
|
|
555
657
|
}
|
|
556
658
|
|
|
557
659
|
// src/jarm/jarm-authorization-response/verify-jarm-authorization-response.ts
|
|
558
|
-
var
|
|
660
|
+
var import_oauth27 = require("@openid4vc/oauth2");
|
|
559
661
|
var import_zod9 = __toESM(require("zod"));
|
|
560
662
|
|
|
561
663
|
// src/jarm/jarm-extract-jwks.ts
|
|
562
|
-
function
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
664
|
+
function extractJwkFromJwks(jwks, {
|
|
665
|
+
kid,
|
|
666
|
+
supportedAlgValues
|
|
667
|
+
}) {
|
|
668
|
+
if (kid) {
|
|
669
|
+
return jwks.keys.find((jwk) => jwk.kid === kid);
|
|
670
|
+
}
|
|
671
|
+
let algFiltered = jwks.keys.filter((key) => key.alg && supportedAlgValues?.includes(key.alg));
|
|
672
|
+
if (algFiltered.length === 0) algFiltered = jwks.keys;
|
|
673
|
+
let encFiltered = algFiltered.filter((key) => key.use === "enc");
|
|
674
|
+
if (!encFiltered) encFiltered = algFiltered.filter((key) => key.use !== "sig");
|
|
675
|
+
return encFiltered.length > 0 ? encFiltered[0] : jwks.keys[0];
|
|
571
676
|
}
|
|
572
677
|
|
|
573
678
|
// src/jarm/jarm-authorization-response/jarm-validate-authorization-response.ts
|
|
574
|
-
var
|
|
679
|
+
var import_oauth26 = require("@openid4vc/oauth2");
|
|
575
680
|
var import_utils6 = require("@openid4vc/utils");
|
|
576
681
|
|
|
577
682
|
// src/jarm/jarm-authorization-response/z-jarm-authorization-response.ts
|
|
578
|
-
var
|
|
683
|
+
var import_oauth25 = require("@openid4vc/oauth2");
|
|
579
684
|
var import_zod8 = require("zod");
|
|
580
|
-
var zJarmHeader = import_zod8.z.object({ ...
|
|
685
|
+
var zJarmHeader = import_zod8.z.object({ ...import_oauth25.zJwtHeader.shape, apu: import_zod8.z.string().optional(), apv: import_zod8.z.string().optional() });
|
|
581
686
|
var zJarmAuthorizationResponse = import_zod8.z.object({
|
|
582
687
|
/**
|
|
583
688
|
* iss: The issuer URL of the authorization server that created the response
|
|
584
689
|
* aud: The client_id of the client the response is intended for
|
|
585
690
|
* exp: The expiration time of the JWT. A maximum JWT lifetime of 10 minutes is RECOMMENDED.
|
|
586
691
|
*/
|
|
587
|
-
...
|
|
588
|
-
...
|
|
692
|
+
...import_oauth25.zJwtPayload.shape,
|
|
693
|
+
...import_oauth25.zJwtPayload.pick({ iss: true, aud: true, exp: true }).required().shape,
|
|
589
694
|
state: import_zod8.z.optional(import_zod8.z.string())
|
|
590
695
|
}).passthrough();
|
|
591
696
|
var zJarmAuthorizationResponseEncryptedOnly = import_zod8.z.object({
|
|
592
|
-
...
|
|
697
|
+
...import_oauth25.zJwtPayload.shape,
|
|
593
698
|
state: import_zod8.z.optional(import_zod8.z.string())
|
|
594
699
|
}).passthrough();
|
|
595
700
|
|
|
@@ -600,12 +705,12 @@ var jarmAuthorizationResponseValidate = (options) => {
|
|
|
600
705
|
return;
|
|
601
706
|
}
|
|
602
707
|
if (expectedClientId !== authorizationResponse.aud) {
|
|
603
|
-
throw new
|
|
708
|
+
throw new import_oauth26.Oauth2Error(
|
|
604
709
|
`Invalid 'aud' claim in JARM authorization response. Expected '${expectedClientId}' received '${JSON.stringify(authorizationResponse.aud)}'.`
|
|
605
710
|
);
|
|
606
711
|
}
|
|
607
712
|
if (authorizationResponse.exp !== void 0 && authorizationResponse.exp < (0, import_utils6.dateToSeconds)()) {
|
|
608
|
-
throw new
|
|
713
|
+
throw new import_oauth26.Oauth2Error("Jarm auth response is expired.");
|
|
609
714
|
}
|
|
610
715
|
};
|
|
611
716
|
|
|
@@ -618,43 +723,51 @@ var JarmMode = /* @__PURE__ */ ((JarmMode2) => {
|
|
|
618
723
|
})(JarmMode || {});
|
|
619
724
|
var decryptJarmAuthorizationResponseJwt = async (options) => {
|
|
620
725
|
const { jarmAuthorizationResponseJwt, callbacks, authorizationRequestPayload } = options;
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
})
|
|
726
|
+
let encryptionJwk = void 0;
|
|
727
|
+
const { header } = (0, import_oauth27.decodeJwtHeader)({
|
|
728
|
+
jwt: jarmAuthorizationResponseJwt
|
|
729
|
+
});
|
|
730
|
+
if (authorizationRequestPayload.client_metadata?.jwks) {
|
|
731
|
+
encryptionJwk = extractJwkFromJwks(authorizationRequestPayload.client_metadata.jwks, {
|
|
732
|
+
// Kid always take precedence
|
|
733
|
+
kid: header.kid,
|
|
734
|
+
// This value was removed in draft 26, but if it's still provided, we can use it to determine the key to use
|
|
735
|
+
supportedAlgValues: authorizationRequestPayload.client_metadata.authorization_encrypted_response_alg ? [authorizationRequestPayload.client_metadata.authorization_encrypted_response_alg] : void 0
|
|
736
|
+
});
|
|
737
|
+
}
|
|
625
738
|
const result = await callbacks.decryptJwe(jarmAuthorizationResponseJwt, { jwk: encryptionJwk });
|
|
626
739
|
if (!result.decrypted) {
|
|
627
|
-
throw new
|
|
740
|
+
throw new import_oauth27.Oauth2Error("Failed to decrypt jarm auth response.");
|
|
628
741
|
}
|
|
629
742
|
return result.payload;
|
|
630
743
|
};
|
|
631
744
|
async function verifyJarmAuthorizationResponse(options) {
|
|
632
745
|
const { jarmAuthorizationResponseJwt, callbacks, expectedClientId, authorizationRequestPayload } = options;
|
|
633
|
-
const requestDataIsEncrypted =
|
|
746
|
+
const requestDataIsEncrypted = import_oauth27.zCompactJwe.safeParse(jarmAuthorizationResponseJwt).success;
|
|
634
747
|
const decryptedRequestData = requestDataIsEncrypted ? await decryptJarmAuthorizationResponseJwt({
|
|
635
748
|
jarmAuthorizationResponseJwt,
|
|
636
749
|
callbacks,
|
|
637
750
|
authorizationRequestPayload
|
|
638
751
|
}) : jarmAuthorizationResponseJwt;
|
|
639
|
-
const responseIsSigned =
|
|
752
|
+
const responseIsSigned = import_oauth27.zCompactJwt.safeParse(decryptedRequestData).success;
|
|
640
753
|
if (!requestDataIsEncrypted && !responseIsSigned) {
|
|
641
|
-
throw new
|
|
754
|
+
throw new import_oauth27.Oauth2Error("Jarm Auth Response must be either encrypted, signed, or signed and encrypted.");
|
|
642
755
|
}
|
|
643
756
|
let jarmAuthorizationResponse;
|
|
644
757
|
if (responseIsSigned) {
|
|
645
|
-
const { header: jwsProtectedHeader, payload: jwsPayload } = (0,
|
|
758
|
+
const { header: jwsProtectedHeader, payload: jwsPayload } = (0, import_oauth27.decodeJwt)({
|
|
646
759
|
jwt: decryptedRequestData,
|
|
647
|
-
headerSchema: import_zod9.default.object({ ...
|
|
760
|
+
headerSchema: import_zod9.default.object({ ...import_oauth27.zJwtHeader.shape, kid: import_zod9.default.string() })
|
|
648
761
|
});
|
|
649
762
|
const response = zJarmAuthorizationResponse.parse(jwsPayload);
|
|
650
|
-
const jwtSigner = (0,
|
|
763
|
+
const jwtSigner = (0, import_oauth27.jwtSignerFromJwt)({ header: jwsProtectedHeader, payload: jwsPayload });
|
|
651
764
|
const verificationResult = await options.callbacks.verifyJwt(jwtSigner, {
|
|
652
765
|
compact: decryptedRequestData,
|
|
653
766
|
header: jwsProtectedHeader,
|
|
654
767
|
payload: jwsPayload
|
|
655
768
|
});
|
|
656
769
|
if (!verificationResult.verified) {
|
|
657
|
-
throw new
|
|
770
|
+
throw new import_oauth27.Oauth2Error("Jarm Auth Response is not valid.");
|
|
658
771
|
}
|
|
659
772
|
jarmAuthorizationResponse = response;
|
|
660
773
|
} else {
|
|
@@ -671,11 +784,11 @@ async function verifyJarmAuthorizationResponse(options) {
|
|
|
671
784
|
}
|
|
672
785
|
|
|
673
786
|
// src/authorization-request/create-authorization-request.ts
|
|
674
|
-
var
|
|
787
|
+
var import_oauth211 = require("@openid4vc/oauth2");
|
|
675
788
|
var import_utils9 = require("@openid4vc/utils");
|
|
676
789
|
|
|
677
790
|
// src/jar/create-jar-authorization-request.ts
|
|
678
|
-
var
|
|
791
|
+
var import_oauth28 = require("@openid4vc/oauth2");
|
|
679
792
|
var import_utils7 = require("@openid4vc/utils");
|
|
680
793
|
async function createJarAuthorizationRequest(options) {
|
|
681
794
|
const { jwtSigner, jweEncryptor, authorizationRequestPayload, requestUri, callbacks } = options;
|
|
@@ -683,7 +796,7 @@ async function createJarAuthorizationRequest(options) {
|
|
|
683
796
|
let encryptionJwk;
|
|
684
797
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
685
798
|
const { jwt, signerJwk } = await callbacks.signJwt(jwtSigner, {
|
|
686
|
-
header: { ...(0,
|
|
799
|
+
header: { ...(0, import_oauth28.jwtHeaderFromJwtSigner)(jwtSigner), typ: "oauth-authz-req+jwt" },
|
|
687
800
|
payload: {
|
|
688
801
|
iat: (0, import_utils7.dateToSeconds)(now),
|
|
689
802
|
exp: (0, import_utils7.dateToSeconds)((0, import_utils7.addSecondsToDate)(now, options.expiresInSeconds)),
|
|
@@ -703,94 +816,94 @@ async function createJarAuthorizationRequest(options) {
|
|
|
703
816
|
}
|
|
704
817
|
|
|
705
818
|
// src/authorization-request/validate-authorization-request.ts
|
|
706
|
-
var
|
|
819
|
+
var import_oauth29 = require("@openid4vc/oauth2");
|
|
707
820
|
var import_utils8 = require("@openid4vc/utils");
|
|
708
821
|
var validateOpenid4vpAuthorizationRequestPayload = (options) => {
|
|
709
822
|
const { params, walletVerificationOptions } = options;
|
|
710
823
|
if (!params.redirect_uri && !params.response_uri) {
|
|
711
|
-
throw new
|
|
712
|
-
error:
|
|
824
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
825
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
713
826
|
error_description: `Missing required 'redirect_uri' or 'response_uri' in openid4vp authorization request.`
|
|
714
827
|
});
|
|
715
828
|
}
|
|
716
829
|
if (params.response_uri && !["direct_post", "direct_post.jwt"].find((mode) => mode === params.response_mode)) {
|
|
717
|
-
throw new
|
|
718
|
-
error:
|
|
830
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
831
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
719
832
|
error_description: `The 'response_mode' parameter MUST be 'direct_post' or 'direct_post.jwt' when 'response_uri' is provided. Current: ${params.response_mode}`
|
|
720
833
|
});
|
|
721
834
|
}
|
|
722
835
|
if ([params.presentation_definition_uri, params.presentation_definition, params.dcql_query, params.scope].filter(
|
|
723
836
|
Boolean
|
|
724
837
|
).length > 1) {
|
|
725
|
-
throw new
|
|
726
|
-
error:
|
|
838
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
839
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
727
840
|
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."
|
|
728
841
|
});
|
|
729
842
|
}
|
|
730
843
|
if (params.request_uri_method && !params.request_uri) {
|
|
731
|
-
throw new
|
|
732
|
-
error:
|
|
844
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
845
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
733
846
|
error_description: 'The "request_uri_method" parameter MUST NOT be present in the authorization request if the "request_uri" parameter is not present.'
|
|
734
847
|
});
|
|
735
848
|
}
|
|
736
849
|
if (params.request_uri_method && !["GET", "POST"].includes(params.request_uri_method)) {
|
|
737
|
-
throw new
|
|
738
|
-
error:
|
|
850
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
851
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequestUriMethod,
|
|
739
852
|
error_description: `The 'request_uri_method' parameter MUST be 'GET' or 'POST'. Current: ${params.request_uri_method}`
|
|
740
853
|
});
|
|
741
854
|
}
|
|
742
855
|
if (params.trust_chain && !import_utils8.zHttpsUrl.safeParse(params.client_id).success) {
|
|
743
|
-
throw new
|
|
744
|
-
error:
|
|
856
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
857
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
745
858
|
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://.'
|
|
746
859
|
});
|
|
747
860
|
}
|
|
748
861
|
if (walletVerificationOptions?.expectedNonce && !params.wallet_nonce) {
|
|
749
|
-
throw new
|
|
750
|
-
error:
|
|
862
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
863
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
751
864
|
error_description: 'The "wallet_nonce" parameter MUST be present in the authorization request when the "expectedNonce" parameter is provided.'
|
|
752
865
|
});
|
|
753
866
|
}
|
|
754
867
|
if (walletVerificationOptions?.expectedNonce !== params.wallet_nonce) {
|
|
755
|
-
throw new
|
|
756
|
-
error:
|
|
868
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
869
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
757
870
|
error_description: 'The "wallet_nonce" parameter MUST match the "expectedNonce" parameter when the "expectedNonce" parameter is provided.'
|
|
758
871
|
});
|
|
759
872
|
}
|
|
760
|
-
if (params.client_id.startsWith("web-origin:")) {
|
|
761
|
-
throw new
|
|
762
|
-
error:
|
|
763
|
-
error_description: `The 'client_id' parameter MUST NOT use client identifier scheme '
|
|
873
|
+
if (params.client_id.startsWith("web-origin:") || params.client_id.startsWith("origin:")) {
|
|
874
|
+
throw new import_oauth29.Oauth2ServerErrorResponseError({
|
|
875
|
+
error: import_oauth29.Oauth2ErrorCodes.InvalidRequest,
|
|
876
|
+
error_description: `The 'client_id' parameter MUST NOT use client identifier scheme '${params.client_id.split(":")[0]}' when not using the dc_api response mode. Current: ${params.client_id}`
|
|
764
877
|
});
|
|
765
878
|
}
|
|
766
879
|
};
|
|
767
880
|
|
|
768
881
|
// src/authorization-request/validate-authorization-request-dc-api.ts
|
|
769
|
-
var
|
|
882
|
+
var import_oauth210 = require("@openid4vc/oauth2");
|
|
770
883
|
var validateOpenid4vpAuthorizationRequestDcApiPayload = (options) => {
|
|
771
884
|
const { params, isJarRequest, disableOriginValidation, origin } = options;
|
|
772
885
|
if (isJarRequest && !params.expected_origins) {
|
|
773
|
-
throw new
|
|
774
|
-
error:
|
|
886
|
+
throw new import_oauth210.Oauth2ServerErrorResponseError({
|
|
887
|
+
error: import_oauth210.Oauth2ErrorCodes.InvalidRequest,
|
|
775
888
|
error_description: `The 'expected_origins' parameter MUST be present when using the dc_api response mode in combinaction with jar.`
|
|
776
889
|
});
|
|
777
890
|
}
|
|
778
891
|
if ([params.presentation_definition, params.dcql_query].filter(Boolean).length !== 1) {
|
|
779
|
-
throw new
|
|
780
|
-
error:
|
|
892
|
+
throw new import_oauth210.Oauth2ServerErrorResponseError({
|
|
893
|
+
error: import_oauth210.Oauth2ErrorCodes.InvalidRequest,
|
|
781
894
|
error_description: "Exactly one of the following parameters MUST be present in the Authorization Request: dcql_query or presentation_definition"
|
|
782
895
|
});
|
|
783
896
|
}
|
|
784
897
|
if (params.expected_origins && !disableOriginValidation) {
|
|
785
898
|
if (!origin) {
|
|
786
|
-
throw new
|
|
787
|
-
error:
|
|
899
|
+
throw new import_oauth210.Oauth2ServerErrorResponseError({
|
|
900
|
+
error: import_oauth210.Oauth2ErrorCodes.InvalidRequest,
|
|
788
901
|
error_description: `Failed to validate the 'origin' of the authorization request. The 'origin' was not provided.`
|
|
789
902
|
});
|
|
790
903
|
}
|
|
791
904
|
if (params.expected_origins && !params.expected_origins.includes(origin)) {
|
|
792
|
-
throw new
|
|
793
|
-
error:
|
|
905
|
+
throw new import_oauth210.Oauth2ServerErrorResponseError({
|
|
906
|
+
error: import_oauth210.Oauth2ErrorCodes.InvalidRequest,
|
|
794
907
|
error_description: `The 'expected_origins' parameter MUST include the origin of the authorization request. Current: ${params.expected_origins.join(", ")}`
|
|
795
908
|
});
|
|
796
909
|
}
|
|
@@ -809,7 +922,7 @@ async function createOpenid4vpAuthorizationRequest(options) {
|
|
|
809
922
|
"Invalid authorization request. Could not parse openid4vp dc_api authorization request."
|
|
810
923
|
);
|
|
811
924
|
if (jar && !authorizationRequestPayload.expected_origins) {
|
|
812
|
-
throw new
|
|
925
|
+
throw new import_oauth211.Oauth2Error(
|
|
813
926
|
`The 'expected_origins' parameter MUST be present when using the dc_api response mode in combination with jar.`
|
|
814
927
|
);
|
|
815
928
|
}
|
|
@@ -867,12 +980,12 @@ async function createOpenid4vpAuthorizationRequest(options) {
|
|
|
867
980
|
}
|
|
868
981
|
|
|
869
982
|
// src/authorization-request/parse-authorization-request-params.ts
|
|
870
|
-
var
|
|
983
|
+
var import_oauth213 = require("@openid4vc/oauth2");
|
|
871
984
|
var import_utils11 = require("@openid4vc/utils");
|
|
872
985
|
var import_zod11 = __toESM(require("zod"));
|
|
873
986
|
|
|
874
987
|
// src/jar/z-jar-authorization-request.ts
|
|
875
|
-
var
|
|
988
|
+
var import_oauth212 = require("@openid4vc/oauth2");
|
|
876
989
|
var import_utils10 = require("@openid4vc/utils");
|
|
877
990
|
var import_zod10 = require("zod");
|
|
878
991
|
var zJarAuthorizationRequest = import_zod10.z.object({
|
|
@@ -884,13 +997,13 @@ var zJarAuthorizationRequest = import_zod10.z.object({
|
|
|
884
997
|
function validateJarRequestParams(options) {
|
|
885
998
|
const { jarRequestParams } = options;
|
|
886
999
|
if (jarRequestParams.request && jarRequestParams.request_uri) {
|
|
887
|
-
throw new
|
|
1000
|
+
throw new import_oauth212.Oauth2ServerErrorResponseError({
|
|
888
1001
|
error: "invalid_request_object",
|
|
889
1002
|
error_description: "request and request_uri cannot both be present in a JAR request"
|
|
890
1003
|
});
|
|
891
1004
|
}
|
|
892
1005
|
if (!jarRequestParams.request && !jarRequestParams.request_uri) {
|
|
893
|
-
throw new
|
|
1006
|
+
throw new import_oauth212.Oauth2ServerErrorResponseError({
|
|
894
1007
|
error: "invalid_request_object",
|
|
895
1008
|
error_description: "request or request_uri must be present"
|
|
896
1009
|
});
|
|
@@ -915,7 +1028,7 @@ function parseOpenid4vpAuthorizationRequest(options) {
|
|
|
915
1028
|
);
|
|
916
1029
|
provided = "uri";
|
|
917
1030
|
} else {
|
|
918
|
-
const decoded = (0,
|
|
1031
|
+
const decoded = (0, import_oauth213.decodeJwt)({ jwt: authorizationRequest });
|
|
919
1032
|
params = decoded.payload;
|
|
920
1033
|
provided = "jwt";
|
|
921
1034
|
}
|
|
@@ -948,12 +1061,12 @@ function parseOpenid4vpAuthorizationRequest(options) {
|
|
|
948
1061
|
}
|
|
949
1062
|
|
|
950
1063
|
// src/authorization-request/resolve-authorization-request.ts
|
|
951
|
-
var
|
|
1064
|
+
var import_oauth220 = require("@openid4vc/oauth2");
|
|
952
1065
|
var import_utils15 = require("@openid4vc/utils");
|
|
953
1066
|
var import_zod15 = __toESM(require("zod"));
|
|
954
1067
|
|
|
955
1068
|
// src/fetch-client-metadata.ts
|
|
956
|
-
var
|
|
1069
|
+
var import_oauth214 = require("@openid4vc/oauth2");
|
|
957
1070
|
var import_utils12 = require("@openid4vc/utils");
|
|
958
1071
|
async function fetchClientMetadata(options) {
|
|
959
1072
|
const { fetch, clientMetadataUri } = options;
|
|
@@ -965,28 +1078,70 @@ async function fetchClientMetadata(options) {
|
|
|
965
1078
|
}
|
|
966
1079
|
});
|
|
967
1080
|
if (!response.ok) {
|
|
968
|
-
throw new
|
|
1081
|
+
throw new import_oauth214.Oauth2ServerErrorResponseError({
|
|
969
1082
|
error_description: `Fetching client metadata from '${clientMetadataUri}' failed with status code '${response.status}'.`,
|
|
970
|
-
error:
|
|
1083
|
+
error: import_oauth214.Oauth2ErrorCodes.InvalidRequestUri
|
|
971
1084
|
});
|
|
972
1085
|
}
|
|
973
1086
|
if (!result || !result.success) {
|
|
974
|
-
throw new
|
|
1087
|
+
throw new import_oauth214.Oauth2ServerErrorResponseError({
|
|
975
1088
|
error_description: `Parsing client metadata from '${clientMetadataUri}' failed.`,
|
|
976
|
-
error:
|
|
1089
|
+
error: import_oauth214.Oauth2ErrorCodes.InvalidRequestObject
|
|
977
1090
|
});
|
|
978
1091
|
}
|
|
979
1092
|
return result.data;
|
|
980
1093
|
}
|
|
981
1094
|
|
|
982
1095
|
// src/jar/handle-jar-request/verify-jar-request.ts
|
|
983
|
-
var
|
|
1096
|
+
var import_oauth218 = require("@openid4vc/oauth2");
|
|
984
1097
|
var import_zod13 = __toESM(require("zod"));
|
|
985
1098
|
|
|
986
1099
|
// src/version.ts
|
|
987
|
-
var
|
|
1100
|
+
var import_oauth215 = require("@openid4vc/oauth2");
|
|
988
1101
|
function parseAuthorizationRequestVersion(request) {
|
|
989
1102
|
const requirements = [];
|
|
1103
|
+
if (request.verifier_info) {
|
|
1104
|
+
requirements.push([">=", 29]);
|
|
1105
|
+
}
|
|
1106
|
+
if (request.verifier_attestations) {
|
|
1107
|
+
requirements.push(["<", 29]);
|
|
1108
|
+
}
|
|
1109
|
+
if (request.client_metadata?.vp_formats_supported?.mso_mdoc?.deviceauth_alg_values || request.client_metadata?.vp_formats_supported?.mso_mdoc?.deviceauth_alg_values) {
|
|
1110
|
+
requirements.push([">=", 28]);
|
|
1111
|
+
}
|
|
1112
|
+
if (request.client_metadata?.vp_formats_supported?.mso_mdoc?.issuer_signed_alg_values || request.client_metadata?.vp_formats_supported?.mso_mdoc?.device_signed_alg_values) {
|
|
1113
|
+
requirements.push(["<", 28]);
|
|
1114
|
+
}
|
|
1115
|
+
if (request.client_metadata?.vp_formats) {
|
|
1116
|
+
requirements.push([">=", 27]);
|
|
1117
|
+
}
|
|
1118
|
+
if (request.client_metadata?.vp_formats_supported) {
|
|
1119
|
+
requirements.push(["<", 27]);
|
|
1120
|
+
}
|
|
1121
|
+
if (request.client_id?.startsWith("openid_federation:") || request.client_id?.startsWith("decentralized_identifier:")) {
|
|
1122
|
+
requirements.push([">=", 26]);
|
|
1123
|
+
}
|
|
1124
|
+
if (request.client_id?.startsWith("did:")) {
|
|
1125
|
+
requirements.push(["<", 26]);
|
|
1126
|
+
}
|
|
1127
|
+
if (request.presentation_definition || request.presentation_definition_uri) {
|
|
1128
|
+
requirements.push([">=", 26]);
|
|
1129
|
+
}
|
|
1130
|
+
if (request.verifier_attestations) {
|
|
1131
|
+
requirements.push([">=", 26]);
|
|
1132
|
+
}
|
|
1133
|
+
if (request.client_id?.startsWith("x509_san_uri:")) {
|
|
1134
|
+
requirements.push(["<", 25]);
|
|
1135
|
+
}
|
|
1136
|
+
if (request.client_id?.startsWith("x509_hash:")) {
|
|
1137
|
+
requirements.push([">=", 25]);
|
|
1138
|
+
}
|
|
1139
|
+
if (request.client_id?.startsWith("web-origin:")) {
|
|
1140
|
+
requirements.push(["<", 25]);
|
|
1141
|
+
}
|
|
1142
|
+
if (request.client_id?.startsWith("origin:")) {
|
|
1143
|
+
requirements.push([">=", 25]);
|
|
1144
|
+
}
|
|
990
1145
|
if (isOpenid4vpAuthorizationRequestDcApi(request) && (request.response_mode === "w3c_dc_api" || request.response_mode === "w3c_dc_api.jwt")) {
|
|
991
1146
|
requirements.push(["<", 23]);
|
|
992
1147
|
requirements.push([">=", 21]);
|
|
@@ -1006,7 +1161,7 @@ function parseAuthorizationRequestVersion(request) {
|
|
|
1006
1161
|
if (request.client_id) {
|
|
1007
1162
|
const colonIndex = request.client_id.indexOf(":");
|
|
1008
1163
|
const schemePart = request.client_id.substring(0, colonIndex);
|
|
1009
|
-
const parsedScheme =
|
|
1164
|
+
const parsedScheme = zClientIdPrefix.safeParse(schemePart);
|
|
1010
1165
|
if (parsedScheme.success && parsedScheme.data !== "did" && parsedScheme.data !== "https") {
|
|
1011
1166
|
requirements.push([">=", 22]);
|
|
1012
1167
|
}
|
|
@@ -1014,6 +1169,9 @@ function parseAuthorizationRequestVersion(request) {
|
|
|
1014
1169
|
if (!request.client_id) {
|
|
1015
1170
|
requirements.push([">=", 21]);
|
|
1016
1171
|
}
|
|
1172
|
+
if (request.dcql_query) {
|
|
1173
|
+
requirements.push([">=", 21]);
|
|
1174
|
+
}
|
|
1017
1175
|
if (request.client_metadata_uri) {
|
|
1018
1176
|
requirements.push(["<", 21]);
|
|
1019
1177
|
}
|
|
@@ -1031,11 +1189,11 @@ function parseAuthorizationRequestVersion(request) {
|
|
|
1031
1189
|
}
|
|
1032
1190
|
const lessThanVersions = requirements.filter(([operator]) => operator === "<").map(([_, version]) => version);
|
|
1033
1191
|
const greaterThanVersions = requirements.filter(([operator]) => operator === ">=").map(([_, version]) => version);
|
|
1034
|
-
const highestPossibleVersion = lessThanVersions.length > 0 ? Math.max(Math.min(...lessThanVersions) - 1, 18) :
|
|
1192
|
+
const highestPossibleVersion = lessThanVersions.length > 0 ? Math.max(Math.min(...lessThanVersions) - 1, 18) : 29;
|
|
1035
1193
|
const lowestRequiredVersion = greaterThanVersions.length > 0 ? Math.max(...greaterThanVersions) : 18;
|
|
1036
1194
|
if (lowestRequiredVersion > highestPossibleVersion) {
|
|
1037
|
-
throw new
|
|
1038
|
-
error:
|
|
1195
|
+
throw new import_oauth215.Oauth2ServerErrorResponseError({
|
|
1196
|
+
error: import_oauth215.Oauth2ErrorCodes.InvalidRequest,
|
|
1039
1197
|
error_description: "Could not infer openid4vp version from the openid4vp request payload."
|
|
1040
1198
|
});
|
|
1041
1199
|
}
|
|
@@ -1043,7 +1201,7 @@ function parseAuthorizationRequestVersion(request) {
|
|
|
1043
1201
|
}
|
|
1044
1202
|
|
|
1045
1203
|
// src/jar/jar-request-object/fetch-jar-request-object.ts
|
|
1046
|
-
var
|
|
1204
|
+
var import_oauth216 = require("@openid4vc/oauth2");
|
|
1047
1205
|
var import_utils13 = require("@openid4vc/utils");
|
|
1048
1206
|
async function fetchJarRequestObject(options) {
|
|
1049
1207
|
const { requestUri, clientIdentifierScheme, method, wallet, fetch } = options;
|
|
@@ -1060,25 +1218,25 @@ async function fetchJarRequestObject(options) {
|
|
|
1060
1218
|
"Content-Type": import_utils13.ContentType.XWwwFormUrlencoded
|
|
1061
1219
|
}
|
|
1062
1220
|
}).catch(() => {
|
|
1063
|
-
throw new
|
|
1221
|
+
throw new import_oauth216.Oauth2ServerErrorResponseError({
|
|
1064
1222
|
error_description: `Fetching request_object from request_uri '${requestUri}' failed`,
|
|
1065
|
-
error:
|
|
1223
|
+
error: import_oauth216.Oauth2ErrorCodes.InvalidRequestUri
|
|
1066
1224
|
});
|
|
1067
1225
|
});
|
|
1068
1226
|
if (!response.ok) {
|
|
1069
|
-
throw new
|
|
1227
|
+
throw new import_oauth216.Oauth2ServerErrorResponseError({
|
|
1070
1228
|
error_description: `Fetching request_object from request_uri '${requestUri}' failed with status code '${response.status}'.`,
|
|
1071
|
-
error:
|
|
1229
|
+
error: import_oauth216.Oauth2ErrorCodes.InvalidRequestUri
|
|
1072
1230
|
});
|
|
1073
1231
|
}
|
|
1074
1232
|
return await response.text();
|
|
1075
1233
|
}
|
|
1076
1234
|
|
|
1077
1235
|
// src/jar/jar-request-object/z-jar-request-object.ts
|
|
1078
|
-
var
|
|
1236
|
+
var import_oauth217 = require("@openid4vc/oauth2");
|
|
1079
1237
|
var import_zod12 = require("zod");
|
|
1080
1238
|
var zJarRequestObjectPayload = import_zod12.z.object({
|
|
1081
|
-
...
|
|
1239
|
+
...import_oauth217.zJwtPayload.shape,
|
|
1082
1240
|
client_id: import_zod12.z.string()
|
|
1083
1241
|
}).passthrough();
|
|
1084
1242
|
|
|
@@ -1089,11 +1247,11 @@ async function verifyJarRequest(options) {
|
|
|
1089
1247
|
const { callbacks, wallet = {} } = options;
|
|
1090
1248
|
const jarRequestParams = validateJarRequestParams(options);
|
|
1091
1249
|
const sendBy = jarRequestParams.request ? "value" : "reference";
|
|
1092
|
-
const clientIdentifierScheme = jarRequestParams.client_id ?
|
|
1250
|
+
const clientIdentifierScheme = jarRequestParams.client_id ? zClientIdPrefix.safeParse(jarRequestParams.client_id.split(":")[0]).data : "origin";
|
|
1093
1251
|
const method = jarRequestParams.request_uri_method ?? "get";
|
|
1094
1252
|
if (method !== "get" && method !== "post") {
|
|
1095
|
-
throw new
|
|
1096
|
-
error:
|
|
1253
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1254
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidRequestUriMethod,
|
|
1097
1255
|
error_description: `Invalid request_uri_method. Must be 'get' or 'post'.`
|
|
1098
1256
|
});
|
|
1099
1257
|
}
|
|
@@ -1104,12 +1262,12 @@ async function verifyJarRequest(options) {
|
|
|
1104
1262
|
wallet,
|
|
1105
1263
|
fetch: callbacks.fetch
|
|
1106
1264
|
});
|
|
1107
|
-
const requestObjectIsEncrypted =
|
|
1265
|
+
const requestObjectIsEncrypted = import_oauth218.zCompactJwe.safeParse(requestObject).success;
|
|
1108
1266
|
const { decryptionJwk, payload: decryptedRequestObject } = requestObjectIsEncrypted ? await decryptJarRequest({ jwe: requestObject, callbacks }) : { payload: requestObject, decryptionJwk: void 0 };
|
|
1109
|
-
const requestIsSigned =
|
|
1267
|
+
const requestIsSigned = import_oauth218.zCompactJwt.safeParse(decryptedRequestObject).success;
|
|
1110
1268
|
if (!requestIsSigned) {
|
|
1111
|
-
throw new
|
|
1112
|
-
error:
|
|
1269
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1270
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidRequestObject,
|
|
1113
1271
|
error_description: "JAR request object is not a valid JWT."
|
|
1114
1272
|
});
|
|
1115
1273
|
}
|
|
@@ -1118,20 +1276,20 @@ async function verifyJarRequest(options) {
|
|
|
1118
1276
|
callbacks
|
|
1119
1277
|
});
|
|
1120
1278
|
if (!authorizationRequestPayload.client_id) {
|
|
1121
|
-
throw new
|
|
1122
|
-
error:
|
|
1279
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1280
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidRequestObject,
|
|
1123
1281
|
error_description: 'Jar Request Object is missing the required "client_id" field.'
|
|
1124
1282
|
});
|
|
1125
1283
|
}
|
|
1126
1284
|
if (!isOpenid4vpResponseModeDcApi(authorizationRequestPayload.response_mode) && jarRequestParams.client_id !== authorizationRequestPayload.client_id) {
|
|
1127
|
-
throw new
|
|
1128
|
-
error:
|
|
1285
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1286
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidRequest,
|
|
1129
1287
|
error_description: "client_id does not match the request object client_id."
|
|
1130
1288
|
});
|
|
1131
1289
|
}
|
|
1132
1290
|
if (jarRequestParams.client_id_scheme && jarRequestParams.client_id_scheme !== authorizationRequestPayload.client_id_scheme) {
|
|
1133
|
-
throw new
|
|
1134
|
-
error:
|
|
1291
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1292
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidRequest,
|
|
1135
1293
|
error_description: "client_id_scheme does not match the request object client_id_scheme."
|
|
1136
1294
|
});
|
|
1137
1295
|
}
|
|
@@ -1145,16 +1303,16 @@ async function verifyJarRequest(options) {
|
|
|
1145
1303
|
}
|
|
1146
1304
|
async function decryptJarRequest(options) {
|
|
1147
1305
|
const { jwe, callbacks } = options;
|
|
1148
|
-
const { header } = (0,
|
|
1306
|
+
const { header } = (0, import_oauth218.decodeJwt)({ jwt: jwe });
|
|
1149
1307
|
if (!header.kid) {
|
|
1150
|
-
throw new
|
|
1151
|
-
error:
|
|
1308
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1309
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidRequestObject,
|
|
1152
1310
|
error_description: 'Jar JWE is missing the protected header field "kid".'
|
|
1153
1311
|
});
|
|
1154
1312
|
}
|
|
1155
1313
|
const decryptionResult = await callbacks.decryptJwe(jwe);
|
|
1156
1314
|
if (!decryptionResult.decrypted) {
|
|
1157
|
-
throw new
|
|
1315
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1158
1316
|
error: "invalid_request_object",
|
|
1159
1317
|
error_description: "Failed to decrypt jar request object."
|
|
1160
1318
|
});
|
|
@@ -1163,17 +1321,17 @@ async function decryptJarRequest(options) {
|
|
|
1163
1321
|
}
|
|
1164
1322
|
async function verifyJarRequestObject(options) {
|
|
1165
1323
|
const { decryptedRequestObject, callbacks } = options;
|
|
1166
|
-
const jwt = (0,
|
|
1324
|
+
const jwt = (0, import_oauth218.decodeJwt)({ jwt: decryptedRequestObject, payloadSchema: zJarRequestObjectPayload });
|
|
1167
1325
|
let jwtSigner;
|
|
1168
|
-
const {
|
|
1326
|
+
const { clientIdPrefix } = getOpenid4vpClientId({
|
|
1169
1327
|
responseMode: jwt.payload.response_mode,
|
|
1170
1328
|
clientId: jwt.payload.client_id,
|
|
1171
1329
|
legacyClientIdScheme: jwt.payload.client_id_scheme
|
|
1172
1330
|
});
|
|
1173
1331
|
const clientIdToSignerMethod = {
|
|
1174
|
-
|
|
1332
|
+
decentralized_identifier: ["did"],
|
|
1175
1333
|
"pre-registered": ["custom", "did", "jwk"],
|
|
1176
|
-
|
|
1334
|
+
origin: [],
|
|
1177
1335
|
// no signing allowed
|
|
1178
1336
|
redirect_uri: [],
|
|
1179
1337
|
// no signing allowed
|
|
@@ -1181,12 +1339,13 @@ async function verifyJarRequestObject(options) {
|
|
|
1181
1339
|
verifier_attestation: ["did", "federation", "jwk", "x5c", "custom"],
|
|
1182
1340
|
x509_san_dns: ["x5c"],
|
|
1183
1341
|
x509_san_uri: ["x5c"],
|
|
1342
|
+
x509_hash: ["x5c"],
|
|
1184
1343
|
// Handled separately
|
|
1185
|
-
|
|
1344
|
+
openid_federation: []
|
|
1186
1345
|
};
|
|
1187
|
-
if (
|
|
1346
|
+
if (clientIdPrefix === "openid_federation") {
|
|
1188
1347
|
if (!jwt.header.kid) {
|
|
1189
|
-
throw new
|
|
1348
|
+
throw new import_oauth218.Oauth2Error(
|
|
1190
1349
|
`When OpenID Federation is used for signed authorization request, the 'kid' parameter is required.`
|
|
1191
1350
|
);
|
|
1192
1351
|
}
|
|
@@ -1197,9 +1356,9 @@ async function verifyJarRequestObject(options) {
|
|
|
1197
1356
|
kid: jwt.header.kid
|
|
1198
1357
|
};
|
|
1199
1358
|
} else {
|
|
1200
|
-
jwtSigner = (0,
|
|
1359
|
+
jwtSigner = (0, import_oauth218.jwtSignerFromJwt)({ ...jwt, allowedSignerMethods: clientIdToSignerMethod[clientIdPrefix] });
|
|
1201
1360
|
}
|
|
1202
|
-
const { signer } = await (0,
|
|
1361
|
+
const { signer } = await (0, import_oauth218.verifyJwt)({
|
|
1203
1362
|
verifyJwtCallback: callbacks.verifyJwt,
|
|
1204
1363
|
compact: decryptedRequestObject,
|
|
1205
1364
|
header: jwt.header,
|
|
@@ -1208,8 +1367,8 @@ async function verifyJarRequestObject(options) {
|
|
|
1208
1367
|
});
|
|
1209
1368
|
const version = parseAuthorizationRequestVersion(jwt.payload);
|
|
1210
1369
|
if (jwt.header.typ !== "oauth-authz-req+jwt" && version >= 24) {
|
|
1211
|
-
throw new
|
|
1212
|
-
error:
|
|
1370
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1371
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidRequestObject,
|
|
1213
1372
|
error_description: `Invalid Jar Request Object typ header. Expected "oauth-authz-req+jwt", received "${jwt.header.typ}".`
|
|
1214
1373
|
});
|
|
1215
1374
|
}
|
|
@@ -1221,7 +1380,7 @@ async function verifyJarRequestObject(options) {
|
|
|
1221
1380
|
}
|
|
1222
1381
|
|
|
1223
1382
|
// src/transaction-data/parse-transaction-data.ts
|
|
1224
|
-
var
|
|
1383
|
+
var import_oauth219 = require("@openid4vc/oauth2");
|
|
1225
1384
|
var import_utils14 = require("@openid4vc/utils");
|
|
1226
1385
|
|
|
1227
1386
|
// src/transaction-data/z-transaction-data.ts
|
|
@@ -1239,8 +1398,8 @@ function parseTransactionData(options) {
|
|
|
1239
1398
|
const decoded = transactionData.map((tdEntry) => (0, import_utils14.parseIfJson)((0, import_utils14.encodeToUtf8String)((0, import_utils14.decodeBase64)(tdEntry))));
|
|
1240
1399
|
const parsedResult = zTransactionData.safeParse(decoded);
|
|
1241
1400
|
if (!parsedResult.success) {
|
|
1242
|
-
throw new
|
|
1243
|
-
error:
|
|
1401
|
+
throw new import_oauth219.Oauth2ServerErrorResponseError({
|
|
1402
|
+
error: import_oauth219.Oauth2ErrorCodes.InvalidTransactionData,
|
|
1244
1403
|
error_description: "Failed to parse transaction data."
|
|
1245
1404
|
});
|
|
1246
1405
|
}
|
|
@@ -1288,7 +1447,7 @@ async function resolveOpenid4vpAuthorizationRequest(options) {
|
|
|
1288
1447
|
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload) && !clientMetadata && authorizationRequestPayload.client_metadata_uri) {
|
|
1289
1448
|
clientMetadata = await fetchClientMetadata({ clientMetadataUri: authorizationRequestPayload.client_metadata_uri });
|
|
1290
1449
|
}
|
|
1291
|
-
const clientMeta = validateOpenid4vpClientId({
|
|
1450
|
+
const clientMeta = await validateOpenid4vpClientId({
|
|
1292
1451
|
authorizationRequestPayload: {
|
|
1293
1452
|
...authorizationRequestPayload,
|
|
1294
1453
|
client_metadata: clientMetadata
|
|
@@ -1301,8 +1460,8 @@ async function resolveOpenid4vpAuthorizationRequest(options) {
|
|
|
1301
1460
|
let dcql;
|
|
1302
1461
|
if (authorizationRequestPayload.presentation_definition || authorizationRequestPayload.presentation_definition_uri) {
|
|
1303
1462
|
if (authorizationRequestPayload.presentation_definition_uri) {
|
|
1304
|
-
throw new
|
|
1305
|
-
error:
|
|
1463
|
+
throw new import_oauth220.Oauth2ServerErrorResponseError({
|
|
1464
|
+
error: import_oauth220.Oauth2ErrorCodes.InvalidRequest,
|
|
1306
1465
|
error_description: "Cannot fetch presentation definition from URI. Not supported."
|
|
1307
1466
|
});
|
|
1308
1467
|
}
|
|
@@ -1321,7 +1480,8 @@ async function resolveOpenid4vpAuthorizationRequest(options) {
|
|
|
1321
1480
|
jar,
|
|
1322
1481
|
client: clientMeta,
|
|
1323
1482
|
pex,
|
|
1324
|
-
dcql
|
|
1483
|
+
dcql,
|
|
1484
|
+
version: parseAuthorizationRequestVersion(authorizationRequestPayload)
|
|
1325
1485
|
};
|
|
1326
1486
|
}
|
|
1327
1487
|
function validateOpenId4vpAuthorizationRequestPayload(options) {
|
|
@@ -1343,7 +1503,7 @@ function validateOpenId4vpAuthorizationRequestPayload(options) {
|
|
|
1343
1503
|
}
|
|
1344
1504
|
|
|
1345
1505
|
// src/authorization-response/create-authorization-response.ts
|
|
1346
|
-
var
|
|
1506
|
+
var import_oauth223 = require("@openid4vc/oauth2");
|
|
1347
1507
|
var import_utils16 = require("@openid4vc/utils");
|
|
1348
1508
|
|
|
1349
1509
|
// ../utils/src/date.ts
|
|
@@ -1352,7 +1512,7 @@ function addSecondsToDate2(date, seconds) {
|
|
|
1352
1512
|
}
|
|
1353
1513
|
|
|
1354
1514
|
// src/jarm/jarm-authorization-response-create.ts
|
|
1355
|
-
var
|
|
1515
|
+
var import_oauth221 = require("@openid4vc/oauth2");
|
|
1356
1516
|
async function createJarmAuthorizationResponse(options) {
|
|
1357
1517
|
const { jarmAuthorizationResponse, jweEncryptor, jwtSigner, callbacks } = options;
|
|
1358
1518
|
if (!jwtSigner && jweEncryptor) {
|
|
@@ -1361,16 +1521,16 @@ async function createJarmAuthorizationResponse(options) {
|
|
|
1361
1521
|
}
|
|
1362
1522
|
if (jwtSigner && !jweEncryptor) {
|
|
1363
1523
|
const signed2 = await callbacks.signJwt(jwtSigner, {
|
|
1364
|
-
header: (0,
|
|
1524
|
+
header: (0, import_oauth221.jwtHeaderFromJwtSigner)(jwtSigner),
|
|
1365
1525
|
payload: jarmAuthorizationResponse
|
|
1366
1526
|
});
|
|
1367
1527
|
return { jarmAuthorizationResponseJwt: signed2.jwt };
|
|
1368
1528
|
}
|
|
1369
1529
|
if (!jwtSigner || !jweEncryptor) {
|
|
1370
|
-
throw new
|
|
1530
|
+
throw new import_oauth221.Oauth2Error("JWT signer and/or encryptor are required to create a JARM auth response.");
|
|
1371
1531
|
}
|
|
1372
1532
|
const signed = await callbacks.signJwt(jwtSigner, {
|
|
1373
|
-
header: (0,
|
|
1533
|
+
header: (0, import_oauth221.jwtHeaderFromJwtSigner)(jwtSigner),
|
|
1374
1534
|
payload: jarmAuthorizationResponse
|
|
1375
1535
|
});
|
|
1376
1536
|
const encrypted = await callbacks.encryptJwe(jweEncryptor, signed.jwt);
|
|
@@ -1393,12 +1553,12 @@ var isJarmResponseMode = (responseMode) => {
|
|
|
1393
1553
|
};
|
|
1394
1554
|
|
|
1395
1555
|
// src/jarm/metadata/jarm-assert-metadata-supported.ts
|
|
1396
|
-
var
|
|
1556
|
+
var import_oauth222 = require("@openid4vc/oauth2");
|
|
1397
1557
|
function assertValueSupported(options) {
|
|
1398
1558
|
const { errorMessage, supported, actual } = options;
|
|
1399
1559
|
const intersection = supported.find((value) => value === actual);
|
|
1400
1560
|
if (!intersection) {
|
|
1401
|
-
throw new
|
|
1561
|
+
throw new import_oauth222.Oauth2Error(errorMessage);
|
|
1402
1562
|
}
|
|
1403
1563
|
return intersection;
|
|
1404
1564
|
}
|
|
@@ -1438,14 +1598,14 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1438
1598
|
...options.authorizationResponsePayload,
|
|
1439
1599
|
state: authorizationRequestPayload.state
|
|
1440
1600
|
};
|
|
1441
|
-
const {
|
|
1601
|
+
const { clientIdPrefix } = getOpenid4vpClientId({
|
|
1442
1602
|
responseMode: authorizationRequestPayload.response_mode,
|
|
1443
1603
|
clientId: authorizationRequestPayload.client_id,
|
|
1444
1604
|
legacyClientIdScheme: authorizationRequestPayload.client_id_scheme,
|
|
1445
1605
|
origin
|
|
1446
1606
|
});
|
|
1447
1607
|
if (authorizationRequestPayload.response_mode && isJarmResponseMode(authorizationRequestPayload.response_mode) && !jarm) {
|
|
1448
|
-
throw new
|
|
1608
|
+
throw new import_oauth223.Oauth2Error(
|
|
1449
1609
|
`Missing jarm options for creating Jarm response with response mode '${authorizationRequestPayload.response_mode}'`
|
|
1450
1610
|
);
|
|
1451
1611
|
}
|
|
@@ -1454,51 +1614,71 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1454
1614
|
authorizationResponsePayload
|
|
1455
1615
|
};
|
|
1456
1616
|
}
|
|
1457
|
-
if (
|
|
1458
|
-
throw new
|
|
1459
|
-
"When OpenID Federation is used as the client id scheme (https), passing externally fetched and verified 'clientMetadata' to the 'createOpenid4vpAuthorizationResponse' is required."
|
|
1617
|
+
if (clientIdPrefix === "openid_federation" && !options.clientMetadata) {
|
|
1618
|
+
throw new import_oauth223.Oauth2Error(
|
|
1619
|
+
"When OpenID Federation is used as the client id scheme (https/openid_federation), passing externally fetched and verified 'clientMetadata' to the 'createOpenid4vpAuthorizationResponse' is required."
|
|
1460
1620
|
);
|
|
1461
1621
|
}
|
|
1462
1622
|
const clientMetadata = options.clientMetadata ?? authorizationRequestPayload.client_metadata;
|
|
1463
1623
|
if (!clientMetadata) {
|
|
1464
|
-
throw new
|
|
1624
|
+
throw new import_oauth223.Oauth2Error("Missing client metadata in the request params to assert Jarm metadata support.");
|
|
1465
1625
|
}
|
|
1466
1626
|
let jwks;
|
|
1467
1627
|
if (clientMetadata.jwks) {
|
|
1468
1628
|
jwks = clientMetadata.jwks;
|
|
1469
1629
|
} else if (clientMetadata.jwks_uri) {
|
|
1470
|
-
jwks = await (0,
|
|
1630
|
+
jwks = await (0, import_oauth223.fetchJwks)(clientMetadata.jwks_uri, options.callbacks.fetch);
|
|
1471
1631
|
} else {
|
|
1472
|
-
throw new
|
|
1473
|
-
error:
|
|
1632
|
+
throw new import_oauth223.Oauth2ServerErrorResponseError({
|
|
1633
|
+
error: import_oauth223.Oauth2ErrorCodes.InvalidRequest,
|
|
1474
1634
|
error_description: `Missing 'jwks' or 'jwks_uri' in client metadata. Cannot extract encryption JWK.`
|
|
1475
1635
|
});
|
|
1476
1636
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1637
|
+
if (clientMetadata.authorization_encrypted_response_alg || clientMetadata.authorization_encrypted_response_env || clientMetadata.authorization_signed_response_alg) {
|
|
1638
|
+
jarmAssertMetadataSupported({
|
|
1639
|
+
clientMetadata,
|
|
1640
|
+
serverMetadata: jarm.serverMetadata
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
const encJwk = extractJwkFromJwks(jwks, {
|
|
1644
|
+
supportedAlgValues: jarm.serverMetadata.authorization_encryption_alg_values_supported ?? (clientMetadata.authorization_encrypted_response_alg ? [clientMetadata.authorization_encrypted_response_alg] : void 0)
|
|
1484
1645
|
});
|
|
1485
|
-
if (!
|
|
1486
|
-
throw new
|
|
1487
|
-
error:
|
|
1646
|
+
if (!encJwk) {
|
|
1647
|
+
throw new import_oauth223.Oauth2ServerErrorResponseError({
|
|
1648
|
+
error: import_oauth223.Oauth2ErrorCodes.InvalidRequest,
|
|
1488
1649
|
error_description: "Could not extract encryption JWK from client metadata. Failed to create JARM response."
|
|
1489
1650
|
});
|
|
1490
1651
|
}
|
|
1652
|
+
let enc;
|
|
1653
|
+
if (clientMetadata.encrypted_response_enc_values_supported) {
|
|
1654
|
+
enc = jarm.serverMetadata.authorization_encryption_enc_values_supported.find(
|
|
1655
|
+
(enc2) => clientMetadata.encrypted_response_enc_values_supported?.includes(enc2)
|
|
1656
|
+
) ?? clientMetadata.encrypted_response_enc_values_supported[0];
|
|
1657
|
+
} else {
|
|
1658
|
+
enc = clientMetadata.authorization_encrypted_response_enc ?? "A128GCM";
|
|
1659
|
+
}
|
|
1660
|
+
assertValueSupported({
|
|
1661
|
+
actual: enc,
|
|
1662
|
+
supported: jarm.serverMetadata.authorization_encryption_enc_values_supported,
|
|
1663
|
+
errorMessage: `Invalid 'enc' value ${enc}. Supported values are ${jarm.serverMetadata.authorization_encryption_enc_values_supported.join(", ")}`
|
|
1664
|
+
});
|
|
1665
|
+
const alg = encJwk.alg ?? clientMetadata.authorization_encrypted_response_alg ?? "ECDH-ES";
|
|
1666
|
+
assertValueSupported({
|
|
1667
|
+
actual: alg,
|
|
1668
|
+
supported: jarm.serverMetadata.authorization_encryption_alg_values_supported,
|
|
1669
|
+
errorMessage: `Invalid 'alg' value ${alg}. Supported values are ${jarm.serverMetadata.authorization_encryption_alg_values_supported.join(", ")}`
|
|
1670
|
+
});
|
|
1491
1671
|
let additionalJwtPayload;
|
|
1492
1672
|
if (jarm?.jwtSigner) {
|
|
1493
1673
|
if (!jarm.authorizationServer) {
|
|
1494
|
-
throw new
|
|
1495
|
-
error:
|
|
1674
|
+
throw new import_oauth223.Oauth2ServerErrorResponseError({
|
|
1675
|
+
error: import_oauth223.Oauth2ErrorCodes.InvalidRequest,
|
|
1496
1676
|
error_description: "Missing required iss in JARM configuration for creating OpenID4VP authorization response."
|
|
1497
1677
|
});
|
|
1498
1678
|
}
|
|
1499
1679
|
if (!jarm.audience) {
|
|
1500
|
-
throw new
|
|
1501
|
-
error:
|
|
1680
|
+
throw new import_oauth223.Oauth2ServerErrorResponseError({
|
|
1681
|
+
error: import_oauth223.Oauth2ErrorCodes.InvalidRequest,
|
|
1502
1682
|
error_description: "Missing required aud in JARM configuration for creating OpenID4VP authorization response."
|
|
1503
1683
|
});
|
|
1504
1684
|
}
|
|
@@ -1516,13 +1696,13 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1516
1696
|
const result = await createJarmAuthorizationResponse({
|
|
1517
1697
|
jarmAuthorizationResponse: jarmResponsePayload,
|
|
1518
1698
|
jwtSigner: jarm?.jwtSigner,
|
|
1519
|
-
jweEncryptor: jarm?.encryption
|
|
1699
|
+
jweEncryptor: jarm?.encryption ? {
|
|
1520
1700
|
method: "jwk",
|
|
1521
|
-
publicJwk:
|
|
1701
|
+
publicJwk: encJwk,
|
|
1522
1702
|
apu: jarm.encryption.nonce ? (0, import_utils16.encodeToBase64Url)(jarm.encryption.nonce) : void 0,
|
|
1523
1703
|
apv: (0, import_utils16.encodeToBase64Url)(authorizationRequestPayload.nonce),
|
|
1524
|
-
alg
|
|
1525
|
-
enc
|
|
1704
|
+
alg,
|
|
1705
|
+
enc
|
|
1526
1706
|
} : void 0,
|
|
1527
1707
|
callbacks: {
|
|
1528
1708
|
signJwt: callbacks.signJwt,
|
|
@@ -1536,18 +1716,18 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1536
1716
|
}
|
|
1537
1717
|
|
|
1538
1718
|
// src/authorization-response/submit-authorization-response.ts
|
|
1539
|
-
var
|
|
1719
|
+
var import_oauth225 = require("@openid4vc/oauth2");
|
|
1540
1720
|
var import_utils18 = require("@openid4vc/utils");
|
|
1541
1721
|
var import_utils19 = require("@openid4vc/utils");
|
|
1542
1722
|
|
|
1543
1723
|
// src/jarm/jarm-authorizatino-response-send.ts
|
|
1544
|
-
var
|
|
1724
|
+
var import_oauth224 = require("@openid4vc/oauth2");
|
|
1545
1725
|
var import_utils17 = require("@openid4vc/utils");
|
|
1546
1726
|
var jarmAuthorizationResponseSend = (options) => {
|
|
1547
1727
|
const { authorizationRequestPayload, jarmAuthorizationResponseJwt, callbacks } = options;
|
|
1548
1728
|
const responseEndpoint = authorizationRequestPayload.response_uri ?? authorizationRequestPayload.redirect_uri;
|
|
1549
1729
|
if (!responseEndpoint) {
|
|
1550
|
-
throw new
|
|
1730
|
+
throw new import_oauth224.Oauth2Error(`Either 'response_uri' or 'redirect_uri' MUST be present in the authorization request`);
|
|
1551
1731
|
}
|
|
1552
1732
|
const responseEndpointUrl = new import_utils17.URL(responseEndpoint);
|
|
1553
1733
|
return handleDirectPostJwt(responseEndpointUrl, jarmAuthorizationResponseJwt, callbacks);
|
|
@@ -1576,7 +1756,7 @@ async function submitOpenid4vpAuthorizationResponse(options) {
|
|
|
1576
1756
|
});
|
|
1577
1757
|
}
|
|
1578
1758
|
if (!url) {
|
|
1579
|
-
throw new
|
|
1759
|
+
throw new import_oauth225.Oauth2Error(
|
|
1580
1760
|
"Failed to submit OpenId4Vp Authorization Response. No redirect_uri or response_uri provided."
|
|
1581
1761
|
);
|
|
1582
1762
|
}
|
|
@@ -1596,7 +1776,7 @@ async function submitOpenid4vpAuthorizationResponse(options) {
|
|
|
1596
1776
|
}
|
|
1597
1777
|
|
|
1598
1778
|
// src/authorization-response/validate-authorization-response.ts
|
|
1599
|
-
var
|
|
1779
|
+
var import_oauth226 = require("@openid4vc/oauth2");
|
|
1600
1780
|
|
|
1601
1781
|
// src/vp-token/parse-vp-token.ts
|
|
1602
1782
|
var import_utils20 = require("@openid4vc/utils");
|
|
@@ -1638,14 +1818,14 @@ function parseDcqlVpToken(vpToken) {
|
|
|
1638
1818
|
function validateOpenid4vpAuthorizationResponsePayload(options) {
|
|
1639
1819
|
const { authorizationRequestPayload, authorizationResponsePayload } = options;
|
|
1640
1820
|
if (authorizationRequestPayload.state && authorizationRequestPayload.state !== authorizationResponsePayload.state) {
|
|
1641
|
-
throw new
|
|
1821
|
+
throw new import_oauth226.Oauth2Error("OpenId4Vp Authorization Response state mismatch.");
|
|
1642
1822
|
}
|
|
1643
1823
|
if (authorizationResponsePayload.id_token) {
|
|
1644
|
-
throw new
|
|
1824
|
+
throw new import_oauth226.Oauth2Error("OpenId4Vp Authorization Response id_token is not supported.");
|
|
1645
1825
|
}
|
|
1646
1826
|
if (authorizationResponsePayload.presentation_submission) {
|
|
1647
1827
|
if (!authorizationRequestPayload.presentation_definition) {
|
|
1648
|
-
throw new
|
|
1828
|
+
throw new import_oauth226.Oauth2Error("OpenId4Vp Authorization Request is missing the required presentation_definition.");
|
|
1649
1829
|
}
|
|
1650
1830
|
return {
|
|
1651
1831
|
type: "pex",
|
|
@@ -1673,13 +1853,13 @@ function validateOpenid4vpAuthorizationResponsePayload(options) {
|
|
|
1673
1853
|
}
|
|
1674
1854
|
};
|
|
1675
1855
|
}
|
|
1676
|
-
throw new
|
|
1856
|
+
throw new import_oauth226.Oauth2Error(
|
|
1677
1857
|
"Invalid OpenId4Vp Authorization Response. Response neither contains a presentation_submission nor request contains a dcql_query."
|
|
1678
1858
|
);
|
|
1679
1859
|
}
|
|
1680
1860
|
|
|
1681
1861
|
// src/authorization-response/parse-authorization-response.ts
|
|
1682
|
-
var
|
|
1862
|
+
var import_oauth228 = require("@openid4vc/oauth2");
|
|
1683
1863
|
|
|
1684
1864
|
// src/authorization-response/parse-authorization-response-payload.ts
|
|
1685
1865
|
var import_utils22 = require("@openid4vc/utils");
|
|
@@ -1715,13 +1895,13 @@ function parseOpenid4VpAuthorizationResponsePayload(payload) {
|
|
|
1715
1895
|
}
|
|
1716
1896
|
|
|
1717
1897
|
// src/authorization-response/parse-jarm-authorization-response.ts
|
|
1718
|
-
var
|
|
1898
|
+
var import_oauth227 = require("@openid4vc/oauth2");
|
|
1719
1899
|
var import_utils23 = require("@openid4vc/utils");
|
|
1720
1900
|
var import_zod20 = __toESM(require("zod"));
|
|
1721
1901
|
async function parseJarmAuthorizationResponse(options) {
|
|
1722
1902
|
const { jarmResponseJwt, callbacks, authorizationRequestPayload, expectedClientId } = options;
|
|
1723
1903
|
const jarmAuthorizationResponseJwt = (0, import_utils23.parseWithErrorHandling)(
|
|
1724
|
-
import_zod20.default.union([
|
|
1904
|
+
import_zod20.default.union([import_oauth227.zCompactJwt, import_oauth227.zCompactJwe]),
|
|
1725
1905
|
jarmResponseJwt,
|
|
1726
1906
|
"Invalid jarm authorization response jwt."
|
|
1727
1907
|
);
|
|
@@ -1731,7 +1911,7 @@ async function parseJarmAuthorizationResponse(options) {
|
|
|
1731
1911
|
expectedClientId,
|
|
1732
1912
|
authorizationRequestPayload
|
|
1733
1913
|
});
|
|
1734
|
-
const { header: jarmHeader } = (0,
|
|
1914
|
+
const { header: jarmHeader } = (0, import_oauth227.decodeJwtHeader)({
|
|
1735
1915
|
jwt: jarmAuthorizationResponseJwt,
|
|
1736
1916
|
headerSchema: zJarmHeader
|
|
1737
1917
|
});
|
|
@@ -1743,7 +1923,7 @@ async function parseJarmAuthorizationResponse(options) {
|
|
|
1743
1923
|
authorizationResponsePayload
|
|
1744
1924
|
});
|
|
1745
1925
|
if (!authorizationRequestPayload.response_mode || !isJarmResponseMode(authorizationRequestPayload.response_mode)) {
|
|
1746
|
-
throw new
|
|
1926
|
+
throw new import_oauth227.Oauth2Error(
|
|
1747
1927
|
`Invalid response mode for jarm response. Response mode: '${authorizationRequestPayload.response_mode ?? "fragment"}'`
|
|
1748
1928
|
);
|
|
1749
1929
|
}
|
|
@@ -1769,9 +1949,7 @@ async function parseOpenid4vpAuthorizationResponse(options) {
|
|
|
1769
1949
|
jarmResponseJwt: authorizationResponse.response,
|
|
1770
1950
|
callbacks,
|
|
1771
1951
|
authorizationRequestPayload,
|
|
1772
|
-
|
|
1773
|
-
// TODO: allow both versions, in case of e.g. did:
|
|
1774
|
-
expectedClientId: expectedClientId.legacyClientId ?? expectedClientId.clientId
|
|
1952
|
+
expectedClientId: expectedClientId.effectiveClientId
|
|
1775
1953
|
});
|
|
1776
1954
|
}
|
|
1777
1955
|
const authorizationResponsePayload = parseOpenid4VpAuthorizationResponsePayload(authorizationResponse);
|
|
@@ -1780,7 +1958,7 @@ async function parseOpenid4vpAuthorizationResponse(options) {
|
|
|
1780
1958
|
authorizationResponsePayload
|
|
1781
1959
|
});
|
|
1782
1960
|
if (authorizationRequestPayload.response_mode && isJarmResponseMode(authorizationRequestPayload.response_mode)) {
|
|
1783
|
-
throw new
|
|
1961
|
+
throw new import_oauth228.Oauth2ServerErrorResponseError(
|
|
1784
1962
|
{
|
|
1785
1963
|
error: "invalid_request",
|
|
1786
1964
|
error_description: "Invalid response mode for openid4vp response. Expected jarm response."
|
|
@@ -1818,7 +1996,7 @@ var Openid4vpClient = class {
|
|
|
1818
1996
|
};
|
|
1819
1997
|
|
|
1820
1998
|
// src/transaction-data/verify-transaction-data.ts
|
|
1821
|
-
var
|
|
1999
|
+
var import_oauth229 = require("@openid4vc/oauth2");
|
|
1822
2000
|
var import_utils24 = require("@openid4vc/utils");
|
|
1823
2001
|
async function verifyTransactionData(options) {
|
|
1824
2002
|
const parsedTransactionData = parseTransactionData({
|
|
@@ -1842,7 +2020,7 @@ async function verifyTransactionDataEntry({
|
|
|
1842
2020
|
}) {
|
|
1843
2021
|
const allowedAlgs = entry.transactionData.transaction_data_hashes_alg ?? ["sha-256"];
|
|
1844
2022
|
const supportedAlgs = allowedAlgs.filter(
|
|
1845
|
-
(alg) => Object.values(
|
|
2023
|
+
(alg) => Object.values(import_oauth229.HashAlgorithm).includes(alg)
|
|
1846
2024
|
);
|
|
1847
2025
|
const hashes = {};
|
|
1848
2026
|
for (const alg of supportedAlgs) {
|
|
@@ -1854,15 +2032,15 @@ async function verifyTransactionDataEntry({
|
|
|
1854
2032
|
const alg = transactionDataHashesCredential.transaction_data_hashes_alg ?? "sha-256";
|
|
1855
2033
|
const hash = hashes[alg];
|
|
1856
2034
|
if (!allowedAlgs.includes(alg)) {
|
|
1857
|
-
throw new
|
|
1858
|
-
error:
|
|
2035
|
+
throw new import_oauth229.Oauth2ServerErrorResponseError({
|
|
2036
|
+
error: import_oauth229.Oauth2ErrorCodes.InvalidTransactionData,
|
|
1859
2037
|
error_description: `Transaction data entry with index ${entry.transactionDataIndex} is hashed using alg '${alg}'. However transaction data only allows alg values ${allowedAlgs.join(", ")}.`
|
|
1860
2038
|
});
|
|
1861
2039
|
}
|
|
1862
2040
|
if (!hash) {
|
|
1863
|
-
throw new
|
|
1864
|
-
error:
|
|
1865
|
-
error_description: `Transaction data entry with index ${entry.transactionDataIndex} is hashed using unsupported alg '${alg}'. This library only supports verification of transaction data hashes using alg values ${Object.values(
|
|
2041
|
+
throw new import_oauth229.Oauth2ServerErrorResponseError({
|
|
2042
|
+
error: import_oauth229.Oauth2ErrorCodes.InvalidTransactionData,
|
|
2043
|
+
error_description: `Transaction data entry with index ${entry.transactionDataIndex} is hashed using unsupported alg '${alg}'. This library only supports verification of transaction data hashes using alg values ${Object.values(import_oauth229.HashAlgorithm).join(", ")}. Either verify the hashes outside of this library, or limit the allowed alg values to the ones supported by this library.`
|
|
1866
2044
|
});
|
|
1867
2045
|
}
|
|
1868
2046
|
const credentialHashIndex = transactionDataHashesCredential.transaction_data_hashes.indexOf(hash);
|
|
@@ -1876,8 +2054,8 @@ async function verifyTransactionDataEntry({
|
|
|
1876
2054
|
};
|
|
1877
2055
|
}
|
|
1878
2056
|
}
|
|
1879
|
-
throw new
|
|
1880
|
-
error:
|
|
2057
|
+
throw new import_oauth229.Oauth2ServerErrorResponseError({
|
|
2058
|
+
error: import_oauth229.Oauth2ErrorCodes.InvalidTransactionData,
|
|
1881
2059
|
error_description: `Transaction data entry with index ${entry.transactionDataIndex} does not have a matching hash in any of the submitted credentials`
|
|
1882
2060
|
});
|
|
1883
2061
|
}
|
|
@@ -1918,7 +2096,7 @@ var Openid4vpVerifier = class {
|
|
|
1918
2096
|
|
|
1919
2097
|
// src/models/z-credential-formats.ts
|
|
1920
2098
|
var import_zod21 = require("zod");
|
|
1921
|
-
var zCredentialFormat = import_zod21.z.enum(["jwt_vc_json", "ldp_vc", "
|
|
2099
|
+
var zCredentialFormat = import_zod21.z.enum(["jwt_vc_json", "ldp_vc", "mso_mdoc", "dc+sd-jwt", "vc+sd-jwt"]);
|
|
1922
2100
|
|
|
1923
2101
|
// src/models/z-proof-formats.ts
|
|
1924
2102
|
var import_zod22 = require("zod");
|
|
@@ -1928,8 +2106,13 @@ var zProofFormat = import_zod22.z.enum(["jwt_vp_json", "ldc_vp", "ac_vp", "dc+sd
|
|
|
1928
2106
|
var import_zod23 = require("zod");
|
|
1929
2107
|
var zWalletMetadata = import_zod23.z.object({
|
|
1930
2108
|
presentation_definition_uri_supported: import_zod23.z.optional(import_zod23.z.boolean()),
|
|
1931
|
-
|
|
1932
|
-
|
|
2109
|
+
// Up until draft 26 the legacy format was used
|
|
2110
|
+
vp_formats_supported: import_zod23.z.optional(zVpFormatsSupported.or(zLegacyVpFormats)),
|
|
2111
|
+
client_id_schemes_supported: import_zod23.z.optional(
|
|
2112
|
+
// client_id_schemes_supported was from before decentralized_identifier and openid_federation were defined
|
|
2113
|
+
import_zod23.z.array(zClientIdPrefix.exclude(["decentralized_identifier", "openid_federation"]))
|
|
2114
|
+
),
|
|
2115
|
+
client_id_prefixes_supported: import_zod23.z.optional(import_zod23.z.array(zUniformClientIdPrefix)),
|
|
1933
2116
|
request_object_signing_alg_values_supported: import_zod23.z.optional(import_zod23.z.array(import_zod23.z.string())),
|
|
1934
2117
|
authorization_encryption_alg_values_supported: import_zod23.z.optional(import_zod23.z.array(import_zod23.z.string())),
|
|
1935
2118
|
authorization_encryption_enc_values_supported: import_zod23.z.optional(import_zod23.z.array(import_zod23.z.string()))
|
|
@@ -1956,7 +2139,7 @@ var zWalletMetadata = import_zod23.z.object({
|
|
|
1956
2139
|
validateOpenid4vpAuthorizationRequestPayload,
|
|
1957
2140
|
validateOpenid4vpAuthorizationResponsePayload,
|
|
1958
2141
|
verifyJarmAuthorizationResponse,
|
|
1959
|
-
|
|
2142
|
+
zClientIdPrefix,
|
|
1960
2143
|
zClientMetadata,
|
|
1961
2144
|
zCredentialFormat,
|
|
1962
2145
|
zJarmClientMetadata,
|