@sd-jwt/sd-jwt-vc 0.17.2-next.0 → 0.17.2-next.10
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 +287 -106
- package/dist/index.d.ts +287 -106
- package/dist/index.js +341 -52
- package/dist/index.mjs +320 -52
- package/package.json +10 -9
- package/src/sd-jwt-vc-config.ts +2 -0
- package/src/sd-jwt-vc-instance.ts +276 -68
- package/src/sd-jwt-vc-payload.ts +1 -1
- package/src/sd-jwt-vc-type-metadata-format.ts +106 -54
- package/src/sd-jwt-vc-vct.ts +1 -1
- package/src/test/index.spec.ts +2 -2
- package/src/test/vct.spec.ts +505 -21
- package/src/verification-result.ts +3 -2
- package/test/app-e2e.spec.ts +13 -7
- package/test/array_data_types.json +1 -1
- package/test/array_full_sd.json +1 -1
- package/test/array_in_sd.json +1 -1
- package/test/array_nested_in_plain.json +1 -1
- package/test/array_none_disclosed.json +1 -1
- package/test/array_of_nulls.json +1 -1
- package/test/array_of_objects.json +1 -1
- package/test/array_of_scalars.json +1 -1
- package/test/array_recursive_sd.json +1 -1
- package/test/array_recursive_sd_some_disclosed.json +1 -1
- package/test/complex.json +1 -1
- package/test/header_mod.json +1 -1
- package/test/json_serialization.json +1 -1
- package/test/key_binding.json +1 -1
- package/test/no_sd.json +1 -1
- package/test/object_data_types.json +1 -1
- package/test/recursions.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
6
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
10
|
var __reflectGet = Reflect.get;
|
|
11
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __spreadValues = (a, b) => {
|
|
13
|
+
for (var prop in b || (b = {}))
|
|
14
|
+
if (__hasOwnProp.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
if (__getOwnPropSymbols)
|
|
17
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
18
|
+
if (__propIsEnum.call(b, prop))
|
|
19
|
+
__defNormalProp(a, prop, b[prop]);
|
|
20
|
+
}
|
|
21
|
+
return a;
|
|
22
|
+
};
|
|
8
23
|
var __export = (target, all) => {
|
|
9
24
|
for (var name in all)
|
|
10
25
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -17,6 +32,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
32
|
}
|
|
18
33
|
return to;
|
|
19
34
|
};
|
|
35
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
36
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
37
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
38
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
39
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
40
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
41
|
+
mod
|
|
42
|
+
));
|
|
20
43
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
44
|
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
22
45
|
var __async = (__this, __arguments, generator) => {
|
|
@@ -43,7 +66,21 @@ var __async = (__this, __arguments, generator) => {
|
|
|
43
66
|
// src/index.ts
|
|
44
67
|
var index_exports = {};
|
|
45
68
|
__export(index_exports, {
|
|
46
|
-
|
|
69
|
+
ClaimDisplaySchema: () => ClaimDisplaySchema,
|
|
70
|
+
ClaimPathSchema: () => ClaimPathSchema,
|
|
71
|
+
ClaimSchema: () => ClaimSchema,
|
|
72
|
+
ClaimSelectiveDisclosureSchema: () => ClaimSelectiveDisclosureSchema,
|
|
73
|
+
ColorSchemeSchema: () => ColorSchemeSchema,
|
|
74
|
+
ContrastSchema: () => ContrastSchema,
|
|
75
|
+
DisplaySchema: () => DisplaySchema,
|
|
76
|
+
LogoSchema: () => LogoSchema,
|
|
77
|
+
OrientationSchema: () => OrientationSchema,
|
|
78
|
+
RenderingSchema: () => RenderingSchema,
|
|
79
|
+
SDJwtVcInstance: () => SDJwtVcInstance,
|
|
80
|
+
SimpleRenderingSchema: () => SimpleRenderingSchema,
|
|
81
|
+
SvgTemplatePropertiesSchema: () => SvgTemplatePropertiesSchema,
|
|
82
|
+
SvgTemplateRenderingSchema: () => SvgTemplateRenderingSchema,
|
|
83
|
+
TypeMetadataFormatSchema: () => TypeMetadataFormatSchema
|
|
47
84
|
});
|
|
48
85
|
module.exports = __toCommonJS(index_exports);
|
|
49
86
|
|
|
@@ -51,6 +88,109 @@ module.exports = __toCommonJS(index_exports);
|
|
|
51
88
|
var import_core = require("@sd-jwt/core");
|
|
52
89
|
var import_jwt_status_list = require("@sd-jwt/jwt-status-list");
|
|
53
90
|
var import_utils = require("@sd-jwt/utils");
|
|
91
|
+
var import_zod2 = __toESM(require("zod"));
|
|
92
|
+
|
|
93
|
+
// src/sd-jwt-vc-type-metadata-format.ts
|
|
94
|
+
var import_zod = require("zod");
|
|
95
|
+
var LogoSchema = import_zod.z.object({
|
|
96
|
+
/** REQUIRED. A URI pointing to the logo image. */
|
|
97
|
+
uri: import_zod.z.string(),
|
|
98
|
+
/** OPTIONAL. An "integrity metadata" string as described in Section 7. */
|
|
99
|
+
"uri#integrity": import_zod.z.string().optional(),
|
|
100
|
+
/** OPTIONAL. A string containing alternative text for the logo image. */
|
|
101
|
+
alt_text: import_zod.z.string().optional()
|
|
102
|
+
});
|
|
103
|
+
var SimpleRenderingSchema = import_zod.z.object({
|
|
104
|
+
/** OPTIONAL. Logo metadata to display for the credential. */
|
|
105
|
+
logo: LogoSchema.optional(),
|
|
106
|
+
/** OPTIONAL. RGB color value for the credential background (e.g., "#FFFFFF"). */
|
|
107
|
+
background_color: import_zod.z.string().optional(),
|
|
108
|
+
/** OPTIONAL. RGB color value for the credential text (e.g., "#000000"). */
|
|
109
|
+
text_color: import_zod.z.string().optional()
|
|
110
|
+
});
|
|
111
|
+
var OrientationSchema = import_zod.z.enum(["portrait", "landscape"]);
|
|
112
|
+
var ColorSchemeSchema = import_zod.z.enum(["light", "dark"]);
|
|
113
|
+
var ContrastSchema = import_zod.z.enum(["normal", "high"]);
|
|
114
|
+
var SvgTemplatePropertiesSchema = import_zod.z.object({
|
|
115
|
+
/** OPTIONAL. Orientation optimized for the template. */
|
|
116
|
+
orientation: OrientationSchema.optional(),
|
|
117
|
+
/** OPTIONAL. Color scheme optimized for the template. */
|
|
118
|
+
color_scheme: ColorSchemeSchema.optional(),
|
|
119
|
+
/** OPTIONAL. Contrast level optimized for the template. */
|
|
120
|
+
contrast: ContrastSchema.optional()
|
|
121
|
+
});
|
|
122
|
+
var SvgTemplateRenderingSchema = import_zod.z.object({
|
|
123
|
+
/** REQUIRED. A URI pointing to the SVG template. */
|
|
124
|
+
uri: import_zod.z.string(),
|
|
125
|
+
/** OPTIONAL. An "integrity metadata" string as described in Section 7. */
|
|
126
|
+
"uri#integrity": import_zod.z.string().optional(),
|
|
127
|
+
/** REQUIRED if more than one SVG template is present. */
|
|
128
|
+
properties: SvgTemplatePropertiesSchema.optional()
|
|
129
|
+
});
|
|
130
|
+
var RenderingSchema = import_zod.z.object({
|
|
131
|
+
/** OPTIONAL. Simple rendering metadata. */
|
|
132
|
+
simple: SimpleRenderingSchema.optional(),
|
|
133
|
+
/** OPTIONAL. Array of SVG template rendering objects. */
|
|
134
|
+
svg_template: import_zod.z.array(SvgTemplateRenderingSchema).optional()
|
|
135
|
+
});
|
|
136
|
+
var DisplaySchema = import_zod.z.object({
|
|
137
|
+
/** REQUIRED. Language tag according to RFC 5646 (e.g., "en", "de"). */
|
|
138
|
+
lang: import_zod.z.string(),
|
|
139
|
+
/** REQUIRED. Human-readable name for the credential type. */
|
|
140
|
+
name: import_zod.z.string(),
|
|
141
|
+
/** OPTIONAL. Description of the credential type for end users. */
|
|
142
|
+
description: import_zod.z.string().optional(),
|
|
143
|
+
/** OPTIONAL. Rendering information (simple or SVG) for the credential. */
|
|
144
|
+
rendering: RenderingSchema.optional()
|
|
145
|
+
});
|
|
146
|
+
var ClaimPathSchema = import_zod.z.array(import_zod.z.string().nullable());
|
|
147
|
+
var ClaimDisplaySchema = import_zod.z.object({
|
|
148
|
+
/** REQUIRED. Language tag according to RFC 5646. */
|
|
149
|
+
lang: import_zod.z.string(),
|
|
150
|
+
/** REQUIRED. Human-readable label for the claim. */
|
|
151
|
+
label: import_zod.z.string(),
|
|
152
|
+
/** OPTIONAL. Description of the claim for end users. */
|
|
153
|
+
description: import_zod.z.string().optional()
|
|
154
|
+
});
|
|
155
|
+
var ClaimSelectiveDisclosureSchema = import_zod.z.enum([
|
|
156
|
+
"always",
|
|
157
|
+
"allowed",
|
|
158
|
+
"never"
|
|
159
|
+
]);
|
|
160
|
+
var ClaimSchema = import_zod.z.object({
|
|
161
|
+
/**
|
|
162
|
+
* REQUIRED. Array of one or more paths to the claim in the credential subject.
|
|
163
|
+
* Each path is an array of strings (or null for array elements).
|
|
164
|
+
*/
|
|
165
|
+
path: ClaimPathSchema,
|
|
166
|
+
/** OPTIONAL. Display metadata in multiple languages. */
|
|
167
|
+
display: import_zod.z.array(ClaimDisplaySchema).optional(),
|
|
168
|
+
/** OPTIONAL. Controls whether the claim must, may, or must not be selectively disclosed. */
|
|
169
|
+
sd: ClaimSelectiveDisclosureSchema.optional(),
|
|
170
|
+
/**
|
|
171
|
+
* OPTIONAL. Unique string identifier for referencing the claim in an SVG template.
|
|
172
|
+
* Must consist of alphanumeric characters or underscores and must not start with a digit.
|
|
173
|
+
*/
|
|
174
|
+
svg_id: import_zod.z.string().optional()
|
|
175
|
+
});
|
|
176
|
+
var TypeMetadataFormatSchema = import_zod.z.object({
|
|
177
|
+
/** REQUIRED. A URI uniquely identifying the credential type. */
|
|
178
|
+
vct: import_zod.z.string(),
|
|
179
|
+
/** OPTIONAL. Human-readable name for developers. */
|
|
180
|
+
name: import_zod.z.string().optional(),
|
|
181
|
+
/** OPTIONAL. Human-readable description for developers. */
|
|
182
|
+
description: import_zod.z.string().optional(),
|
|
183
|
+
/** OPTIONAL. URI of another type that this one extends. */
|
|
184
|
+
extends: import_zod.z.string().optional(),
|
|
185
|
+
/** OPTIONAL. Integrity metadata for the 'extends' field. */
|
|
186
|
+
"extends#integrity": import_zod.z.string().optional(),
|
|
187
|
+
/** OPTIONAL. Array of localized display metadata for the type. */
|
|
188
|
+
display: import_zod.z.array(DisplaySchema).optional(),
|
|
189
|
+
/** OPTIONAL. Array of claim metadata. */
|
|
190
|
+
claims: import_zod.z.array(ClaimSchema).optional()
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// src/sd-jwt-vc-instance.ts
|
|
54
194
|
var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
55
195
|
constructor(userConfig) {
|
|
56
196
|
super(userConfig);
|
|
@@ -131,13 +271,17 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
131
271
|
});
|
|
132
272
|
yield this.verifyStatus(result, options);
|
|
133
273
|
if (this.userConfig.loadTypeMetadataFormat) {
|
|
134
|
-
yield this.
|
|
274
|
+
const resolvedTypeMetadata = yield this.fetchVct(result);
|
|
275
|
+
result.typeMetadata = resolvedTypeMetadata;
|
|
135
276
|
}
|
|
136
277
|
return result;
|
|
137
278
|
});
|
|
138
279
|
}
|
|
139
280
|
/**
|
|
140
281
|
* Gets VCT Metadata of the raw SD-JWT-VC. Returns the type metadata format. If the SD-JWT-VC is invalid or does not contain a vct claim, an error is thrown.
|
|
282
|
+
*
|
|
283
|
+
* It may return `undefined` if the fetcher returned an undefined value (instead of throwing an error).
|
|
284
|
+
*
|
|
141
285
|
* @param encodedSDJwt
|
|
142
286
|
* @returns
|
|
143
287
|
*/
|
|
@@ -162,20 +306,19 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
162
306
|
*/
|
|
163
307
|
validateIntegrity(response, url, integrity) {
|
|
164
308
|
return __async(this, null, function* () {
|
|
165
|
-
if (integrity)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
309
|
+
if (!integrity) return;
|
|
310
|
+
const arrayBuffer = yield response.arrayBuffer();
|
|
311
|
+
const alg = integrity.split("-")[0];
|
|
312
|
+
const hashBuffer = yield this.userConfig.hasher(
|
|
313
|
+
arrayBuffer,
|
|
314
|
+
alg
|
|
315
|
+
);
|
|
316
|
+
const integrityHash = integrity.split("-")[1];
|
|
317
|
+
const hash = Array.from(new Uint8Array(hashBuffer)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
318
|
+
if (hash !== integrityHash) {
|
|
319
|
+
throw new Error(
|
|
320
|
+
`Integrity check for ${url} failed: is ${hash}, but expected ${integrityHash}`
|
|
171
321
|
);
|
|
172
|
-
const integrityHash = integrity.split("-")[1];
|
|
173
|
-
const hash = Array.from(new Uint8Array(hashBuffer)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
174
|
-
if (hash !== integrityHash) {
|
|
175
|
-
throw new Error(
|
|
176
|
-
`Integrity check for ${url} failed: is ${hash}, but expected ${integrityHash}`
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
322
|
}
|
|
180
323
|
});
|
|
181
324
|
}
|
|
@@ -184,7 +327,7 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
184
327
|
* @param url
|
|
185
328
|
* @returns
|
|
186
329
|
*/
|
|
187
|
-
|
|
330
|
+
fetchWithIntegrity(url, integrity) {
|
|
188
331
|
return __async(this, null, function* () {
|
|
189
332
|
var _a;
|
|
190
333
|
try {
|
|
@@ -198,7 +341,8 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
198
341
|
);
|
|
199
342
|
}
|
|
200
343
|
yield this.validateIntegrity(response.clone(), url, integrity);
|
|
201
|
-
|
|
344
|
+
const data = yield response.json();
|
|
345
|
+
return data;
|
|
202
346
|
} catch (error) {
|
|
203
347
|
if (error.name === "TimeoutError") {
|
|
204
348
|
throw new Error(`Request to ${url} timed out`);
|
|
@@ -209,59 +353,190 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
209
353
|
}
|
|
210
354
|
/**
|
|
211
355
|
* Verifies the VCT of the SD-JWT-VC. Returns the type metadata format.
|
|
356
|
+
* Resolves the full extends chain according to spec sections 6.4, 8.2, and 9.5.
|
|
212
357
|
* @param result
|
|
213
358
|
* @returns
|
|
214
359
|
*/
|
|
215
|
-
|
|
360
|
+
fetchVct(result) {
|
|
216
361
|
return __async(this, null, function* () {
|
|
217
|
-
const typeMetadataFormat = yield this.
|
|
218
|
-
|
|
362
|
+
const typeMetadataFormat = yield this.fetchSingleVct(
|
|
363
|
+
result.payload.vct,
|
|
364
|
+
result.payload["vct#integrity"]
|
|
365
|
+
);
|
|
366
|
+
if (!typeMetadataFormat) return void 0;
|
|
367
|
+
if (!typeMetadataFormat.extends) {
|
|
368
|
+
return {
|
|
369
|
+
mergedTypeMetadata: typeMetadataFormat,
|
|
370
|
+
typeMetadataChain: [typeMetadataFormat],
|
|
371
|
+
vctValues: [typeMetadataFormat.vct]
|
|
372
|
+
};
|
|
219
373
|
}
|
|
220
|
-
return typeMetadataFormat;
|
|
374
|
+
return this.resolveVctExtendsChain(typeMetadataFormat);
|
|
221
375
|
});
|
|
222
376
|
}
|
|
223
377
|
/**
|
|
224
|
-
*
|
|
225
|
-
* @param
|
|
226
|
-
* @
|
|
378
|
+
* Checks if two claim paths are equal by comparing each element.
|
|
379
|
+
* @param path1 First claim path
|
|
380
|
+
* @param path2 Second claim path
|
|
381
|
+
* @returns True if paths are equal, false otherwise
|
|
227
382
|
*/
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
383
|
+
claimPathsEqual(path1, path2) {
|
|
384
|
+
if (path1.length !== path2.length) return false;
|
|
385
|
+
return path1.every((element, index) => element === path2[index]);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Validates that extending claim metadata respects the constraints from spec section 9.5.1.
|
|
389
|
+
* @param baseClaim The base claim metadata
|
|
390
|
+
* @param extendingClaim The extending claim metadata
|
|
391
|
+
* @throws SDJWTException if validation fails
|
|
392
|
+
*/
|
|
393
|
+
validateClaimExtension(baseClaim, extendingClaim) {
|
|
394
|
+
if (baseClaim.sd && extendingClaim.sd) {
|
|
395
|
+
if ((baseClaim.sd === "always" || baseClaim.sd === "never") && baseClaim.sd !== extendingClaim.sd) {
|
|
396
|
+
const pathStr = JSON.stringify(extendingClaim.path);
|
|
397
|
+
throw new import_utils.SDJWTException(
|
|
398
|
+
`Cannot change 'sd' property from '${baseClaim.sd}' to '${extendingClaim.sd}' for claim at path ${pathStr}`
|
|
399
|
+
);
|
|
233
400
|
}
|
|
234
|
-
|
|
235
|
-
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Merges two type metadata formats, with the extending metadata overriding the base metadata.
|
|
405
|
+
* According to spec section 9.5:
|
|
406
|
+
* - All claim metadata from the extended type are inherited
|
|
407
|
+
* - The child type can add new claims or properties
|
|
408
|
+
* - If the child type defines claim metadata with the same path as the extended type,
|
|
409
|
+
* the child type's object will override the corresponding object from the extended type
|
|
410
|
+
* According to spec section 9.5.1:
|
|
411
|
+
* - sd property can only be changed from 'allowed' (or omitted) to 'always' or 'never'
|
|
412
|
+
* - sd property cannot be changed from 'always' or 'never' to a different value
|
|
413
|
+
* According to spec section 8.2:
|
|
414
|
+
* - If the extending type defines its own display property, the original display metadata is ignored
|
|
415
|
+
* Note: The spec also mentions 'mandatory' property constraints, but this is not currently
|
|
416
|
+
* defined in the Claim type and will be validated when that property is added to the type.
|
|
417
|
+
* @param base The base type metadata format
|
|
418
|
+
* @param extending The extending type metadata format
|
|
419
|
+
* @returns The merged type metadata format
|
|
420
|
+
*/
|
|
421
|
+
mergeTypeMetadata(base, extending) {
|
|
422
|
+
var _a, _b;
|
|
423
|
+
const merged = __spreadValues({}, extending);
|
|
424
|
+
if (base.claims || extending.claims) {
|
|
425
|
+
const baseClaims = (_a = base.claims) != null ? _a : [];
|
|
426
|
+
const extendingClaims = (_b = extending.claims) != null ? _b : [];
|
|
427
|
+
for (const extendingClaim of extendingClaims) {
|
|
428
|
+
const matchingBaseClaim = baseClaims.find(
|
|
429
|
+
(baseClaim) => this.claimPathsEqual(baseClaim.path, extendingClaim.path)
|
|
430
|
+
);
|
|
431
|
+
if (matchingBaseClaim) {
|
|
432
|
+
this.validateClaimExtension(matchingBaseClaim, extendingClaim);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const mergedClaims = [];
|
|
436
|
+
const extendedClaimsWithoutBase = [...extendingClaims];
|
|
437
|
+
for (const baseClaim of baseClaims) {
|
|
438
|
+
const extendingClaimIndex = extendedClaimsWithoutBase.findIndex(
|
|
439
|
+
(extendingClaim2) => this.claimPathsEqual(baseClaim.path, extendingClaim2.path)
|
|
440
|
+
);
|
|
441
|
+
const extendingClaim = extendingClaimIndex !== -1 ? extendedClaimsWithoutBase[extendingClaimIndex] : void 0;
|
|
442
|
+
if (extendingClaim) {
|
|
443
|
+
extendedClaimsWithoutBase.splice(extendingClaimIndex, 1);
|
|
444
|
+
}
|
|
445
|
+
mergedClaims.push(extendingClaim != null ? extendingClaim : baseClaim);
|
|
446
|
+
}
|
|
447
|
+
mergedClaims.push(...extendedClaimsWithoutBase);
|
|
448
|
+
merged.claims = mergedClaims;
|
|
449
|
+
}
|
|
450
|
+
if (!extending.display && base.display) {
|
|
451
|
+
merged.display = base.display;
|
|
452
|
+
}
|
|
453
|
+
return merged;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Resolves the full VCT chain by recursively fetching extended type metadata.
|
|
457
|
+
* Implements security considerations from spec section 10.3 for circular dependencies.
|
|
458
|
+
* @param vct The VCT URI to resolve
|
|
459
|
+
* @param integrity Optional integrity metadata for the VCT
|
|
460
|
+
* @param depth Current depth in the chain
|
|
461
|
+
* @param visitedVcts Set of already visited VCT URIs to detect circular dependencies
|
|
462
|
+
* @returns The fully resolved and merged type metadata format
|
|
463
|
+
*/
|
|
464
|
+
resolveVctExtendsChain(_0) {
|
|
465
|
+
return __async(this, arguments, function* (parentTypeMetadata, depth = 1, visitedVcts = new Set(parentTypeMetadata.vct)) {
|
|
466
|
+
var _a;
|
|
467
|
+
const maxDepth = (_a = this.userConfig.maxVctExtendsDepth) != null ? _a : 5;
|
|
468
|
+
if (maxDepth !== -1 && depth > maxDepth) {
|
|
469
|
+
throw new import_utils.SDJWTException(
|
|
470
|
+
`Maximum VCT extends depth of ${maxDepth} exceeded`
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
if (!parentTypeMetadata.extends) {
|
|
474
|
+
throw new import_utils.SDJWTException(
|
|
475
|
+
`Type metadata for vct '${parentTypeMetadata.vct}' has no 'extends' field. Unable to resolve extended type metadata document.`
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
if (visitedVcts.has(parentTypeMetadata.extends)) {
|
|
479
|
+
throw new import_utils.SDJWTException(
|
|
480
|
+
`Circular dependency detected in VCT extends chain: ${parentTypeMetadata.extends}`
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
visitedVcts.add(parentTypeMetadata.extends);
|
|
484
|
+
const extendedTypeMetadata = yield this.fetchSingleVct(
|
|
485
|
+
parentTypeMetadata.extends,
|
|
486
|
+
parentTypeMetadata["extends#integrity"]
|
|
487
|
+
);
|
|
488
|
+
if (!extendedTypeMetadata) {
|
|
489
|
+
throw new import_utils.SDJWTException(
|
|
490
|
+
`Resolving VCT extends value '${parentTypeMetadata.extends}' resulted in an undefined result.`
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
let resolvedTypeMetadata;
|
|
494
|
+
if (extendedTypeMetadata.extends) {
|
|
495
|
+
resolvedTypeMetadata = yield this.resolveVctExtendsChain(
|
|
496
|
+
extendedTypeMetadata,
|
|
497
|
+
depth + 1,
|
|
498
|
+
visitedVcts
|
|
499
|
+
);
|
|
500
|
+
} else {
|
|
501
|
+
resolvedTypeMetadata = {
|
|
502
|
+
mergedTypeMetadata: extendedTypeMetadata,
|
|
503
|
+
typeMetadataChain: [extendedTypeMetadata],
|
|
504
|
+
vctValues: [extendedTypeMetadata.vct]
|
|
505
|
+
};
|
|
236
506
|
}
|
|
237
|
-
const
|
|
238
|
-
|
|
507
|
+
const mergedTypeMetadata = this.mergeTypeMetadata(
|
|
508
|
+
resolvedTypeMetadata.mergedTypeMetadata,
|
|
509
|
+
parentTypeMetadata
|
|
510
|
+
);
|
|
511
|
+
return {
|
|
512
|
+
mergedTypeMetadata,
|
|
513
|
+
typeMetadataChain: [
|
|
514
|
+
parentTypeMetadata,
|
|
515
|
+
...resolvedTypeMetadata.typeMetadataChain
|
|
516
|
+
],
|
|
517
|
+
vctValues: [parentTypeMetadata.vct, ...resolvedTypeMetadata.vctValues]
|
|
518
|
+
};
|
|
239
519
|
});
|
|
240
520
|
}
|
|
241
521
|
/**
|
|
242
|
-
* Fetches
|
|
522
|
+
* Fetches and verifies the VCT Metadata for a VCT value.
|
|
243
523
|
* @param result
|
|
244
|
-
* @
|
|
524
|
+
* @returns
|
|
245
525
|
*/
|
|
246
|
-
|
|
526
|
+
fetchSingleVct(vct, integrity) {
|
|
247
527
|
return __async(this, null, function* () {
|
|
248
528
|
var _a;
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}).find((typeMetadataFormat2) => {
|
|
259
|
-
return typeMetadataFormat2.vct === vct;
|
|
260
|
-
});
|
|
261
|
-
if (!typeMetadataFormat) {
|
|
262
|
-
throw new Error("could not find VCT Metadata in JWT header");
|
|
529
|
+
const fetcher = (_a = this.userConfig.vctFetcher) != null ? _a : ((uri, integrity2) => this.fetchWithIntegrity(uri, integrity2));
|
|
530
|
+
const data = yield fetcher(vct, integrity);
|
|
531
|
+
if (!data) return void 0;
|
|
532
|
+
const validated = TypeMetadataFormatSchema.safeParse(data);
|
|
533
|
+
if (!validated.success) {
|
|
534
|
+
throw new import_utils.SDJWTException(
|
|
535
|
+
`Invalid VCT type metadata for vct '${vct}':
|
|
536
|
+
${import_zod2.default.prettifyError(validated.error)}`
|
|
537
|
+
);
|
|
263
538
|
}
|
|
264
|
-
return
|
|
539
|
+
return validated.data;
|
|
265
540
|
});
|
|
266
541
|
}
|
|
267
542
|
/**
|
|
@@ -301,5 +576,19 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
301
576
|
};
|
|
302
577
|
// Annotate the CommonJS export names for ESM import in node:
|
|
303
578
|
0 && (module.exports = {
|
|
304
|
-
|
|
579
|
+
ClaimDisplaySchema,
|
|
580
|
+
ClaimPathSchema,
|
|
581
|
+
ClaimSchema,
|
|
582
|
+
ClaimSelectiveDisclosureSchema,
|
|
583
|
+
ColorSchemeSchema,
|
|
584
|
+
ContrastSchema,
|
|
585
|
+
DisplaySchema,
|
|
586
|
+
LogoSchema,
|
|
587
|
+
OrientationSchema,
|
|
588
|
+
RenderingSchema,
|
|
589
|
+
SDJwtVcInstance,
|
|
590
|
+
SimpleRenderingSchema,
|
|
591
|
+
SvgTemplatePropertiesSchema,
|
|
592
|
+
SvgTemplateRenderingSchema,
|
|
593
|
+
TypeMetadataFormatSchema
|
|
305
594
|
});
|