@sd-jwt/sd-jwt-vc 0.12.1-next.2 → 0.12.1-next.3
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 +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +31 -2
- package/dist/index.mjs +32 -3
- package/package.json +7 -7
- package/src/sd-jwt-vc-instance.ts +39 -1
- package/src/test/vct.spec.ts +31 -9
package/dist/index.d.mts
CHANGED
|
@@ -254,6 +254,12 @@ declare class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
|
|
|
254
254
|
* @returns
|
|
255
255
|
*/
|
|
256
256
|
private fetchVct;
|
|
257
|
+
/**
|
|
258
|
+
* Fetches VCT Metadata from the header of the SD-JWT-VC. Returns the type metadata format. If the SD-JWT-VC does not contain a vct claim, an error is thrown.
|
|
259
|
+
* @param result
|
|
260
|
+
* @param
|
|
261
|
+
*/
|
|
262
|
+
private fetchVctFromHeader;
|
|
257
263
|
/**
|
|
258
264
|
* Verifies the status of the SD-JWT-VC.
|
|
259
265
|
* @param result
|
package/dist/index.d.ts
CHANGED
|
@@ -254,6 +254,12 @@ declare class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
|
|
|
254
254
|
* @returns
|
|
255
255
|
*/
|
|
256
256
|
private fetchVct;
|
|
257
|
+
/**
|
|
258
|
+
* Fetches VCT Metadata from the header of the SD-JWT-VC. Returns the type metadata format. If the SD-JWT-VC does not contain a vct claim, an error is thrown.
|
|
259
|
+
* @param result
|
|
260
|
+
* @param
|
|
261
|
+
*/
|
|
262
|
+
private fetchVctFromHeader;
|
|
257
263
|
/**
|
|
258
264
|
* Verifies the status of the SD-JWT-VC.
|
|
259
265
|
* @param result
|
package/dist/index.js
CHANGED
|
@@ -281,14 +281,43 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
281
281
|
*/
|
|
282
282
|
fetchVct(result) {
|
|
283
283
|
return __async(this, null, function* () {
|
|
284
|
-
var _a;
|
|
284
|
+
var _a, _b;
|
|
285
285
|
if (!result.payload.vct) {
|
|
286
286
|
throw new import_utils.SDJWTException("vct claim is required");
|
|
287
287
|
}
|
|
288
|
-
|
|
288
|
+
if ((_a = result.header) == null ? void 0 : _a.vctm) {
|
|
289
|
+
return this.fetchVctFromHeader(result.payload.vct, result);
|
|
290
|
+
}
|
|
291
|
+
const fetcher = (_b = this.userConfig.vctFetcher) != null ? _b : (uri, integrity) => this.fetch(uri, integrity);
|
|
289
292
|
return fetcher(result.payload.vct, result.payload["vct#Integrity"]);
|
|
290
293
|
});
|
|
291
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Fetches VCT Metadata from the header of the SD-JWT-VC. Returns the type metadata format. If the SD-JWT-VC does not contain a vct claim, an error is thrown.
|
|
297
|
+
* @param result
|
|
298
|
+
* @param
|
|
299
|
+
*/
|
|
300
|
+
fetchVctFromHeader(vct, result) {
|
|
301
|
+
return __async(this, null, function* () {
|
|
302
|
+
var _a;
|
|
303
|
+
const vctmHeader = (_a = result.header) == null ? void 0 : _a.vctm;
|
|
304
|
+
if (!vctmHeader || !Array.isArray(vctmHeader)) {
|
|
305
|
+
throw new Error("vctm claim in SD JWT header is invalid");
|
|
306
|
+
}
|
|
307
|
+
const typeMetadataFormat = vctmHeader.map((vctm) => {
|
|
308
|
+
if (!(typeof vctm === "string")) {
|
|
309
|
+
throw new Error("vctm claim in SD JWT header is invalid");
|
|
310
|
+
}
|
|
311
|
+
return JSON.parse((0, import_utils.base64urlDecode)(vctm));
|
|
312
|
+
}).find((typeMetadataFormat2) => {
|
|
313
|
+
return typeMetadataFormat2.vct === vct;
|
|
314
|
+
});
|
|
315
|
+
if (!typeMetadataFormat) {
|
|
316
|
+
throw new Error("could not find VCT Metadata in JWT header");
|
|
317
|
+
}
|
|
318
|
+
return typeMetadataFormat;
|
|
319
|
+
});
|
|
320
|
+
}
|
|
292
321
|
/**
|
|
293
322
|
* Verifies the status of the SD-JWT-VC.
|
|
294
323
|
* @param result
|
package/dist/index.mjs
CHANGED
|
@@ -24,7 +24,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
24
24
|
|
|
25
25
|
// src/sd-jwt-vc-instance.ts
|
|
26
26
|
import { Jwt, SDJwt, SDJwtInstance } from "@sd-jwt/core";
|
|
27
|
-
import { SDJWTException } from "@sd-jwt/utils";
|
|
27
|
+
import { base64urlDecode, SDJWTException } from "@sd-jwt/utils";
|
|
28
28
|
import {
|
|
29
29
|
getListFromStatusListJWT
|
|
30
30
|
} from "@sd-jwt/jwt-status-list";
|
|
@@ -249,14 +249,43 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends SDJwtInstance {
|
|
|
249
249
|
*/
|
|
250
250
|
fetchVct(result) {
|
|
251
251
|
return __async(this, null, function* () {
|
|
252
|
-
var _a;
|
|
252
|
+
var _a, _b;
|
|
253
253
|
if (!result.payload.vct) {
|
|
254
254
|
throw new SDJWTException("vct claim is required");
|
|
255
255
|
}
|
|
256
|
-
|
|
256
|
+
if ((_a = result.header) == null ? void 0 : _a.vctm) {
|
|
257
|
+
return this.fetchVctFromHeader(result.payload.vct, result);
|
|
258
|
+
}
|
|
259
|
+
const fetcher = (_b = this.userConfig.vctFetcher) != null ? _b : (uri, integrity) => this.fetch(uri, integrity);
|
|
257
260
|
return fetcher(result.payload.vct, result.payload["vct#Integrity"]);
|
|
258
261
|
});
|
|
259
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Fetches VCT Metadata from the header of the SD-JWT-VC. Returns the type metadata format. If the SD-JWT-VC does not contain a vct claim, an error is thrown.
|
|
265
|
+
* @param result
|
|
266
|
+
* @param
|
|
267
|
+
*/
|
|
268
|
+
fetchVctFromHeader(vct, result) {
|
|
269
|
+
return __async(this, null, function* () {
|
|
270
|
+
var _a;
|
|
271
|
+
const vctmHeader = (_a = result.header) == null ? void 0 : _a.vctm;
|
|
272
|
+
if (!vctmHeader || !Array.isArray(vctmHeader)) {
|
|
273
|
+
throw new Error("vctm claim in SD JWT header is invalid");
|
|
274
|
+
}
|
|
275
|
+
const typeMetadataFormat = vctmHeader.map((vctm) => {
|
|
276
|
+
if (!(typeof vctm === "string")) {
|
|
277
|
+
throw new Error("vctm claim in SD JWT header is invalid");
|
|
278
|
+
}
|
|
279
|
+
return JSON.parse(base64urlDecode(vctm));
|
|
280
|
+
}).find((typeMetadataFormat2) => {
|
|
281
|
+
return typeMetadataFormat2.vct === vct;
|
|
282
|
+
});
|
|
283
|
+
if (!typeMetadataFormat) {
|
|
284
|
+
throw new Error("could not find VCT Metadata in JWT header");
|
|
285
|
+
}
|
|
286
|
+
return typeMetadataFormat;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
260
289
|
/**
|
|
261
290
|
* Verifies the status of the SD-JWT-VC.
|
|
262
291
|
* @param result
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/sd-jwt-vc",
|
|
3
|
-
"version": "0.12.1-next.
|
|
3
|
+
"version": "0.12.1-next.3+f89ba44",
|
|
4
4
|
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
},
|
|
40
40
|
"license": "Apache-2.0",
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@sd-jwt/core": "0.12.1-next.
|
|
43
|
-
"@sd-jwt/jwt-status-list": "0.12.1-next.
|
|
44
|
-
"@sd-jwt/utils": "0.12.1-next.
|
|
42
|
+
"@sd-jwt/core": "0.12.1-next.3+f89ba44",
|
|
43
|
+
"@sd-jwt/jwt-status-list": "0.12.1-next.3+f89ba44",
|
|
44
|
+
"@sd-jwt/utils": "0.12.1-next.3+f89ba44",
|
|
45
45
|
"ajv": "^8.17.1",
|
|
46
46
|
"ajv-formats": "^3.0.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@sd-jwt/crypto-nodejs": "0.12.1-next.
|
|
50
|
-
"@sd-jwt/types": "0.12.1-next.
|
|
49
|
+
"@sd-jwt/crypto-nodejs": "0.12.1-next.3+f89ba44",
|
|
50
|
+
"@sd-jwt/types": "0.12.1-next.3+f89ba44",
|
|
51
51
|
"jose": "^5.2.2",
|
|
52
52
|
"msw": "^2.3.5"
|
|
53
53
|
},
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"esm"
|
|
68
68
|
]
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "f89ba445aeb57ce342ec76b58a0eb6d0c090a4e9"
|
|
71
71
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Jwt, SDJwt, SDJwtInstance, type VerifierOptions } from '@sd-jwt/core';
|
|
2
2
|
import type { DisclosureFrame, Hasher, Verifier } from '@sd-jwt/types';
|
|
3
|
-
import { SDJWTException } from '@sd-jwt/utils';
|
|
3
|
+
import { base64urlDecode, SDJWTException } from '@sd-jwt/utils';
|
|
4
4
|
import type { SdJwtVcPayload } from './sd-jwt-vc-payload';
|
|
5
5
|
import type {
|
|
6
6
|
SDJWTVCConfig,
|
|
@@ -294,12 +294,50 @@ export class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
|
|
|
294
294
|
throw new SDJWTException('vct claim is required');
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
if (result.header?.vctm) {
|
|
298
|
+
return this.fetchVctFromHeader(result.payload.vct, result);
|
|
299
|
+
}
|
|
300
|
+
|
|
297
301
|
const fetcher: VcTFetcher =
|
|
298
302
|
this.userConfig.vctFetcher ??
|
|
299
303
|
((uri, integrity) => this.fetch(uri, integrity));
|
|
300
304
|
return fetcher(result.payload.vct, result.payload['vct#Integrity']);
|
|
301
305
|
}
|
|
302
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Fetches VCT Metadata from the header of the SD-JWT-VC. Returns the type metadata format. If the SD-JWT-VC does not contain a vct claim, an error is thrown.
|
|
309
|
+
* @param result
|
|
310
|
+
* @param
|
|
311
|
+
*/
|
|
312
|
+
private async fetchVctFromHeader(
|
|
313
|
+
vct: string,
|
|
314
|
+
result: VerificationResult,
|
|
315
|
+
): Promise<TypeMetadataFormat> {
|
|
316
|
+
const vctmHeader = result.header?.vctm;
|
|
317
|
+
|
|
318
|
+
if (!vctmHeader || !Array.isArray(vctmHeader)) {
|
|
319
|
+
throw new Error('vctm claim in SD JWT header is invalid');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const typeMetadataFormat = (vctmHeader as unknown[])
|
|
323
|
+
.map((vctm) => {
|
|
324
|
+
if (!(typeof vctm === 'string')) {
|
|
325
|
+
throw new Error('vctm claim in SD JWT header is invalid');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return JSON.parse(base64urlDecode(vctm));
|
|
329
|
+
})
|
|
330
|
+
.find((typeMetadataFormat) => {
|
|
331
|
+
return typeMetadataFormat.vct === vct;
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
if (!typeMetadataFormat) {
|
|
335
|
+
throw new Error('could not find VCT Metadata in JWT header');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return typeMetadataFormat;
|
|
339
|
+
}
|
|
340
|
+
|
|
303
341
|
/**
|
|
304
342
|
* Verifies the status of the SD-JWT-VC.
|
|
305
343
|
* @param result
|
package/src/test/vct.spec.ts
CHANGED
|
@@ -9,6 +9,16 @@ import { HttpResponse, http } from 'msw';
|
|
|
9
9
|
import { afterEach } from 'node:test';
|
|
10
10
|
import type { TypeMetadataFormat } from '../sd-jwt-vc-type-metadata-format';
|
|
11
11
|
|
|
12
|
+
const exampleVctm = {
|
|
13
|
+
vct: 'http://example.com/example',
|
|
14
|
+
name: 'ExampleCredentialType',
|
|
15
|
+
description: 'An example credential type',
|
|
16
|
+
schema_uri: 'http://example.com/schema/example',
|
|
17
|
+
//this value could be generated on demand to make it easier when changing the values
|
|
18
|
+
'schema_uri#Integrity':
|
|
19
|
+
'sha256-48a61b283ded3b55e8d9a9b063327641dc4c53f76bd5daa96c23f232822167ae',
|
|
20
|
+
};
|
|
21
|
+
|
|
12
22
|
const restHandlers = [
|
|
13
23
|
http.get('http://example.com/schema/example', () => {
|
|
14
24
|
const res = {
|
|
@@ -42,15 +52,7 @@ const restHandlers = [
|
|
|
42
52
|
return HttpResponse.json(res);
|
|
43
53
|
}),
|
|
44
54
|
http.get('http://example.com/example', () => {
|
|
45
|
-
const res: TypeMetadataFormat =
|
|
46
|
-
vct: 'http://example.com/example',
|
|
47
|
-
name: 'ExampleCredentialType',
|
|
48
|
-
description: 'An example credential type',
|
|
49
|
-
schema_uri: 'http://example.com/schema/example',
|
|
50
|
-
//this value could be generated on demand to make it easier when changing the values
|
|
51
|
-
'schema_uri#Integrity':
|
|
52
|
-
'sha256-48a61b283ded3b55e8d9a9b063327641dc4c53f76bd5daa96c23f232822167ae',
|
|
53
|
-
};
|
|
55
|
+
const res: TypeMetadataFormat = exampleVctm;
|
|
54
56
|
return HttpResponse.json(res);
|
|
55
57
|
}),
|
|
56
58
|
http.get('http://example.com/timeout', () => {
|
|
@@ -133,6 +135,26 @@ describe('App', () => {
|
|
|
133
135
|
await sdjwt.verify(encodedSdjwt);
|
|
134
136
|
});
|
|
135
137
|
|
|
138
|
+
test('VCT from JWT header Validation', async () => {
|
|
139
|
+
const expectedPayload: SdJwtVcPayload = {
|
|
140
|
+
iat,
|
|
141
|
+
iss,
|
|
142
|
+
vct,
|
|
143
|
+
'vct#Integrity': vctIntegrity,
|
|
144
|
+
...claims,
|
|
145
|
+
};
|
|
146
|
+
const header = {
|
|
147
|
+
vctm: [Buffer.from(JSON.stringify(exampleVctm)).toString('base64url')],
|
|
148
|
+
};
|
|
149
|
+
const encodedSdjwt = await sdjwt.issue(
|
|
150
|
+
expectedPayload,
|
|
151
|
+
disclosureFrame as unknown as DisclosureFrame<SdJwtVcPayload>,
|
|
152
|
+
{ header },
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
await sdjwt.verify(encodedSdjwt);
|
|
156
|
+
});
|
|
157
|
+
|
|
136
158
|
test('VCT Validation with timeout', async () => {
|
|
137
159
|
const vct = 'http://example.com/timeout';
|
|
138
160
|
const expectedPayload: SdJwtVcPayload = {
|