@sd-jwt/sd-jwt-vc 0.19.1-next.0 → 0.19.1-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/README.md +66 -10
- package/dist/index.d.mts +42 -14
- package/dist/index.d.ts +42 -14
- package/dist/index.js +129 -23
- package/dist/index.mjs +125 -13
- package/package.json +5 -7
- package/src/sd-jwt-vc-config.ts +3 -3
- package/src/sd-jwt-vc-instance.ts +148 -15
- package/src/sd-jwt-vc-type-metadata-format.ts +15 -3
- package/src/sd-jwt-vc-vct.ts +1 -1
- package/src/test/index.spec.ts +3 -3
- package/src/test/vct.spec.ts +2 -2
- package/src/verification-result.ts +1 -1
- package/test/app-e2e.spec.ts +2 -2
- package/CHANGELOG.md +0 -282
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|

|
|
2
|
-

|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
### About
|
|
11
11
|
|
|
12
|
-
SD-JWT-VC
|
|
12
|
+
Implementation of [SD-JWT-based Verifiable Credentials (SD-JWT VC) — draft-ietf-oauth-sd-jwt-vc-15](https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-15.html), built on top of `@sd-jwt/core` ([RFC 9901](https://www.rfc-editor.org/rfc/rfc9901.html)).
|
|
13
13
|
|
|
14
14
|
Check the detail description in our github [repo](https://github.com/openwallet-foundation/sd-jwt-js).
|
|
15
15
|
|
|
@@ -34,8 +34,8 @@ Ensure you have Node.js installed as a prerequisite.
|
|
|
34
34
|
|
|
35
35
|
Here's a basic example of how to use this library:
|
|
36
36
|
|
|
37
|
-
```
|
|
38
|
-
import { DisclosureFrame } from '@sd-jwt/
|
|
37
|
+
```typescript
|
|
38
|
+
import type { DisclosureFrame } from '@sd-jwt/core';
|
|
39
39
|
|
|
40
40
|
// identifier of the issuer
|
|
41
41
|
const iss = 'University';
|
|
@@ -85,7 +85,7 @@ Check out more details in our [documentation](https://github.com/openwallet-foun
|
|
|
85
85
|
|
|
86
86
|
### Revocation
|
|
87
87
|
|
|
88
|
-
To add revocation capabilities, you can use the `@
|
|
88
|
+
To add revocation capabilities, you can use the `@owf/token-status-list` library to create a JWT Status List and include it in the SD-JWT-VC.
|
|
89
89
|
|
|
90
90
|
You can pass a dedicated `statusVerifier` function in the configuration to verify the signature of the payload of the JWT of the statuslist. If no function is provided, it will fallback to the verifier that is also used for the sd-jwt-vc.
|
|
91
91
|
|
|
@@ -105,13 +105,69 @@ const sdjwt = new SDJwtVcInstance({
|
|
|
105
105
|
});
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
The library will load
|
|
108
|
+
The library will load the type metadata format based on the `vct` value according to the [SD-JWT-VC specification](https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-15.html#name-sd-jwt-vc-type-metadata) and validate this schema.
|
|
109
109
|
|
|
110
110
|
Since at this point the display is not yet implemented, the library will only validate the schema and return the type metadata format. In the future the values of the type metadata can be fetched via a function call.
|
|
111
111
|
|
|
112
|
+
### Verification
|
|
113
|
+
|
|
114
|
+
The library provides two verification approaches:
|
|
115
|
+
|
|
116
|
+
#### Standard Verification (Fail-Fast)
|
|
117
|
+
|
|
118
|
+
The `verify()` method throws an error immediately when the first validation failure is encountered:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
try {
|
|
122
|
+
const result = await sdjwt.verify(presentation);
|
|
123
|
+
console.log('Verified payload:', result.payload);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error('Verification failed:', error.message);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Safe Verification (Collect All Errors)
|
|
130
|
+
|
|
131
|
+
The `safeVerify()` method collects all validation errors instead of failing on the first one. This is useful when you want to show users all issues with a credential at once, including signature, status (revocation), and VCT metadata validation:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import type { SafeVerifyResult, VerificationError } from '@sd-jwt/core';
|
|
135
|
+
|
|
136
|
+
const result = await sdjwt.safeVerify(presentation);
|
|
137
|
+
|
|
138
|
+
if (result.success) {
|
|
139
|
+
// Verification succeeded
|
|
140
|
+
console.log('Verified payload:', result.payload);
|
|
141
|
+
console.log('Header:', result.header);
|
|
142
|
+
if (result.kb) {
|
|
143
|
+
console.log('Key binding:', result.kb);
|
|
144
|
+
}
|
|
145
|
+
if (result.typeMetadata) {
|
|
146
|
+
console.log('Type metadata:', result.typeMetadata);
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
// Verification failed - inspect all errors
|
|
150
|
+
for (const error of result.errors) {
|
|
151
|
+
console.error(`[${error.code}] ${error.message}`);
|
|
152
|
+
if (error.details) {
|
|
153
|
+
console.error('Details:', error.details);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
##### SD-JWT-VC Specific Error Codes
|
|
160
|
+
|
|
161
|
+
In addition to the [core error codes](../core/README.md#error-codes), `safeVerify()` in SD-JWT-VC can return:
|
|
162
|
+
|
|
163
|
+
| Code | Description |
|
|
164
|
+
|------|-------------|
|
|
165
|
+
| `STATUS_VERIFICATION_FAILED` | Status list fetch or verification failed |
|
|
166
|
+
| `STATUS_INVALID` | Credential status indicates revocation |
|
|
167
|
+
| `VCT_VERIFICATION_FAILED` | VCT type metadata fetch or validation failed |
|
|
168
|
+
|
|
112
169
|
### Dependencies
|
|
113
170
|
|
|
114
|
-
- @sd-jwt/core
|
|
115
|
-
- @
|
|
116
|
-
-
|
|
117
|
-
- @sd-jwt/jwt-status-list
|
|
171
|
+
- [@sd-jwt/core](https://www.npmjs.com/package/@sd-jwt/core)
|
|
172
|
+
- [@owf/token-status-list](https://www.npmjs.com/package/@owf/token-status-list)
|
|
173
|
+
- [zod](https://www.npmjs.com/package/zod)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { SDJWTConfig, Verifier, kbPayload, kbHeader, DisclosureFrame } from '@sd-jwt/
|
|
1
|
+
import { SDJWTConfig, Verifier, SdJwtPayload, kbPayload, kbHeader, SDJwtInstance, DisclosureFrame, VerifierOptions, SafeVerifyResult } from '@sd-jwt/core';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { SdJwtPayload, SDJwtInstance, VerifierOptions } from '@sd-jwt/core';
|
|
4
3
|
|
|
5
4
|
declare const BackgroundImageSchema: z.ZodObject<{
|
|
6
5
|
/** REQUIRED. A URI pointing to the background image. */
|
|
@@ -517,18 +516,24 @@ declare const ClaimDisplaySchema: z.ZodPipe<z.ZodObject<{
|
|
|
517
516
|
*/
|
|
518
517
|
locale: z.ZodOptional<z.ZodString>;
|
|
519
518
|
/** REQUIRED. Human-readable label for the claim. */
|
|
520
|
-
label: z.ZodString
|
|
519
|
+
label: z.ZodOptional<z.ZodString>;
|
|
520
|
+
/**
|
|
521
|
+
* Human-readable label for the claim.
|
|
522
|
+
* @deprecated - use `label` instead
|
|
523
|
+
*/
|
|
524
|
+
name: z.ZodOptional<z.ZodString>;
|
|
521
525
|
/** OPTIONAL. Description of the claim for end users. */
|
|
522
526
|
description: z.ZodOptional<z.ZodString>;
|
|
523
527
|
}, z.core.$loose>, z.ZodTransform<{
|
|
524
528
|
locale: string | undefined;
|
|
525
|
-
label: string;
|
|
529
|
+
label: string | undefined;
|
|
526
530
|
description?: string | undefined;
|
|
527
531
|
}, {
|
|
528
532
|
[x: string]: unknown;
|
|
529
|
-
label: string;
|
|
530
533
|
lang?: string | undefined;
|
|
531
534
|
locale?: string | undefined;
|
|
535
|
+
label?: string | undefined;
|
|
536
|
+
name?: string | undefined;
|
|
532
537
|
description?: string | undefined;
|
|
533
538
|
}>>;
|
|
534
539
|
type ClaimDisplay = z.infer<typeof ClaimDisplaySchema>;
|
|
@@ -563,18 +568,24 @@ declare const ClaimSchema: z.ZodObject<{
|
|
|
563
568
|
*/
|
|
564
569
|
locale: z.ZodOptional<z.ZodString>;
|
|
565
570
|
/** REQUIRED. Human-readable label for the claim. */
|
|
566
|
-
label: z.ZodString
|
|
571
|
+
label: z.ZodOptional<z.ZodString>;
|
|
572
|
+
/**
|
|
573
|
+
* Human-readable label for the claim.
|
|
574
|
+
* @deprecated - use `label` instead
|
|
575
|
+
*/
|
|
576
|
+
name: z.ZodOptional<z.ZodString>;
|
|
567
577
|
/** OPTIONAL. Description of the claim for end users. */
|
|
568
578
|
description: z.ZodOptional<z.ZodString>;
|
|
569
579
|
}, z.core.$loose>, z.ZodTransform<{
|
|
570
580
|
locale: string | undefined;
|
|
571
|
-
label: string;
|
|
581
|
+
label: string | undefined;
|
|
572
582
|
description?: string | undefined;
|
|
573
583
|
}, {
|
|
574
584
|
[x: string]: unknown;
|
|
575
|
-
label: string;
|
|
576
585
|
lang?: string | undefined;
|
|
577
586
|
locale?: string | undefined;
|
|
587
|
+
label?: string | undefined;
|
|
588
|
+
name?: string | undefined;
|
|
578
589
|
description?: string | undefined;
|
|
579
590
|
}>>>>;
|
|
580
591
|
/** OPTIONAL. Controls whether the claim must, may, or must not be selectively disclosed. */
|
|
@@ -862,18 +873,24 @@ declare const TypeMetadataFormatSchema: z.ZodObject<{
|
|
|
862
873
|
*/
|
|
863
874
|
locale: z.ZodOptional<z.ZodString>;
|
|
864
875
|
/** REQUIRED. Human-readable label for the claim. */
|
|
865
|
-
label: z.ZodString
|
|
876
|
+
label: z.ZodOptional<z.ZodString>;
|
|
877
|
+
/**
|
|
878
|
+
* Human-readable label for the claim.
|
|
879
|
+
* @deprecated - use `label` instead
|
|
880
|
+
*/
|
|
881
|
+
name: z.ZodOptional<z.ZodString>;
|
|
866
882
|
/** OPTIONAL. Description of the claim for end users. */
|
|
867
883
|
description: z.ZodOptional<z.ZodString>;
|
|
868
884
|
}, z.core.$loose>, z.ZodTransform<{
|
|
869
885
|
locale: string | undefined;
|
|
870
|
-
label: string;
|
|
886
|
+
label: string | undefined;
|
|
871
887
|
description?: string | undefined;
|
|
872
888
|
}, {
|
|
873
889
|
[x: string]: unknown;
|
|
874
|
-
label: string;
|
|
875
890
|
lang?: string | undefined;
|
|
876
891
|
locale?: string | undefined;
|
|
892
|
+
label?: string | undefined;
|
|
893
|
+
name?: string | undefined;
|
|
877
894
|
description?: string | undefined;
|
|
878
895
|
}>>>>;
|
|
879
896
|
/** OPTIONAL. Controls whether the claim must, may, or must not be selectively disclosed. */
|
|
@@ -915,7 +932,7 @@ type ResolvedTypeMetadata = {
|
|
|
915
932
|
};
|
|
916
933
|
type TypeMetadataFormat = z.infer<typeof TypeMetadataFormatSchema>;
|
|
917
934
|
|
|
918
|
-
type
|
|
935
|
+
type VCTFetcher = (uri: string, integrity?: string) => Promise<TypeMetadataFormat | undefined>;
|
|
919
936
|
|
|
920
937
|
type StatusListFetcher = (uri: string) => Promise<string>;
|
|
921
938
|
type StatusValidator = (status: number) => Promise<void>;
|
|
@@ -925,7 +942,7 @@ type StatusValidator = (status: number) => Promise<void>;
|
|
|
925
942
|
type SDJWTVCConfig = SDJWTConfig & {
|
|
926
943
|
statusListFetcher?: StatusListFetcher;
|
|
927
944
|
statusValidator?: StatusValidator;
|
|
928
|
-
vctFetcher?:
|
|
945
|
+
vctFetcher?: VCTFetcher;
|
|
929
946
|
statusVerifier?: Verifier;
|
|
930
947
|
loadTypeMetadataFormat?: boolean;
|
|
931
948
|
timeout?: number;
|
|
@@ -990,6 +1007,16 @@ declare class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
|
|
|
990
1007
|
* @param currentDate current time in seconds
|
|
991
1008
|
*/
|
|
992
1009
|
verify(encodedSDJwt: string, options?: VerifierOptions): Promise<VerificationResult>;
|
|
1010
|
+
/**
|
|
1011
|
+
* Safe verification that collects all errors instead of failing fast.
|
|
1012
|
+
* Returns a result object with either the verified data or an array of all errors.
|
|
1013
|
+
* This includes SD-JWT-VC specific validations like status and VCT metadata.
|
|
1014
|
+
*
|
|
1015
|
+
* @param encodedSDJwt - The encoded SD-JWT-VC to verify
|
|
1016
|
+
* @param options - Verification options
|
|
1017
|
+
* @returns A SafeVerifyResult containing either success data or collected errors
|
|
1018
|
+
*/
|
|
1019
|
+
safeVerify(encodedSDJwt: string, options?: VerifierOptions): Promise<SafeVerifyResult<VerificationResult>>;
|
|
993
1020
|
/**
|
|
994
1021
|
* 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.
|
|
995
1022
|
*
|
|
@@ -1073,6 +1100,7 @@ declare class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
|
|
|
1073
1100
|
* @param options
|
|
1074
1101
|
*/
|
|
1075
1102
|
private verifyStatus;
|
|
1103
|
+
config(newConfig: SDJWTVCConfig): void;
|
|
1076
1104
|
}
|
|
1077
1105
|
|
|
1078
|
-
export { type BackgroundImage, BackgroundImageSchema, type Claim, type ClaimDisplay, ClaimDisplaySchema, type ClaimPath, ClaimPathSchema, ClaimSchema, type ClaimSelectiveDisclosure, ClaimSelectiveDisclosureSchema, ColorSchemeSchema, ContrastSchema, type Display, DisplaySchema, type Logo, LogoSchema, OrientationSchema, type Rendering, RenderingSchema, type ResolvedTypeMetadata, type SDJWTVCConfig, type SDJWTVCStatusReference, SDJwtVcInstance, type SdJwtVcPayload, type SimpleRendering, SimpleRenderingSchema, type StatusListFetcher, type StatusValidator, type SvgTemplateProperties, SvgTemplatePropertiesSchema, type SvgTemplateRendering, SvgTemplateRenderingSchema, type TypeMetadataFormat, TypeMetadataFormatSchema, type
|
|
1106
|
+
export { type BackgroundImage, BackgroundImageSchema, type Claim, type ClaimDisplay, ClaimDisplaySchema, type ClaimPath, ClaimPathSchema, ClaimSchema, type ClaimSelectiveDisclosure, ClaimSelectiveDisclosureSchema, ColorSchemeSchema, ContrastSchema, type Display, DisplaySchema, type Logo, LogoSchema, OrientationSchema, type Rendering, RenderingSchema, type ResolvedTypeMetadata, type SDJWTVCConfig, type SDJWTVCStatusReference, SDJwtVcInstance, type SdJwtVcPayload, type SimpleRendering, SimpleRenderingSchema, type StatusListFetcher, type StatusValidator, type SvgTemplateProperties, SvgTemplatePropertiesSchema, type SvgTemplateRendering, SvgTemplateRenderingSchema, type TypeMetadataFormat, TypeMetadataFormatSchema, type VCTFetcher, type VerificationResult };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { SDJWTConfig, Verifier, kbPayload, kbHeader, DisclosureFrame } from '@sd-jwt/
|
|
1
|
+
import { SDJWTConfig, Verifier, SdJwtPayload, kbPayload, kbHeader, SDJwtInstance, DisclosureFrame, VerifierOptions, SafeVerifyResult } from '@sd-jwt/core';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { SdJwtPayload, SDJwtInstance, VerifierOptions } from '@sd-jwt/core';
|
|
4
3
|
|
|
5
4
|
declare const BackgroundImageSchema: z.ZodObject<{
|
|
6
5
|
/** REQUIRED. A URI pointing to the background image. */
|
|
@@ -517,18 +516,24 @@ declare const ClaimDisplaySchema: z.ZodPipe<z.ZodObject<{
|
|
|
517
516
|
*/
|
|
518
517
|
locale: z.ZodOptional<z.ZodString>;
|
|
519
518
|
/** REQUIRED. Human-readable label for the claim. */
|
|
520
|
-
label: z.ZodString
|
|
519
|
+
label: z.ZodOptional<z.ZodString>;
|
|
520
|
+
/**
|
|
521
|
+
* Human-readable label for the claim.
|
|
522
|
+
* @deprecated - use `label` instead
|
|
523
|
+
*/
|
|
524
|
+
name: z.ZodOptional<z.ZodString>;
|
|
521
525
|
/** OPTIONAL. Description of the claim for end users. */
|
|
522
526
|
description: z.ZodOptional<z.ZodString>;
|
|
523
527
|
}, z.core.$loose>, z.ZodTransform<{
|
|
524
528
|
locale: string | undefined;
|
|
525
|
-
label: string;
|
|
529
|
+
label: string | undefined;
|
|
526
530
|
description?: string | undefined;
|
|
527
531
|
}, {
|
|
528
532
|
[x: string]: unknown;
|
|
529
|
-
label: string;
|
|
530
533
|
lang?: string | undefined;
|
|
531
534
|
locale?: string | undefined;
|
|
535
|
+
label?: string | undefined;
|
|
536
|
+
name?: string | undefined;
|
|
532
537
|
description?: string | undefined;
|
|
533
538
|
}>>;
|
|
534
539
|
type ClaimDisplay = z.infer<typeof ClaimDisplaySchema>;
|
|
@@ -563,18 +568,24 @@ declare const ClaimSchema: z.ZodObject<{
|
|
|
563
568
|
*/
|
|
564
569
|
locale: z.ZodOptional<z.ZodString>;
|
|
565
570
|
/** REQUIRED. Human-readable label for the claim. */
|
|
566
|
-
label: z.ZodString
|
|
571
|
+
label: z.ZodOptional<z.ZodString>;
|
|
572
|
+
/**
|
|
573
|
+
* Human-readable label for the claim.
|
|
574
|
+
* @deprecated - use `label` instead
|
|
575
|
+
*/
|
|
576
|
+
name: z.ZodOptional<z.ZodString>;
|
|
567
577
|
/** OPTIONAL. Description of the claim for end users. */
|
|
568
578
|
description: z.ZodOptional<z.ZodString>;
|
|
569
579
|
}, z.core.$loose>, z.ZodTransform<{
|
|
570
580
|
locale: string | undefined;
|
|
571
|
-
label: string;
|
|
581
|
+
label: string | undefined;
|
|
572
582
|
description?: string | undefined;
|
|
573
583
|
}, {
|
|
574
584
|
[x: string]: unknown;
|
|
575
|
-
label: string;
|
|
576
585
|
lang?: string | undefined;
|
|
577
586
|
locale?: string | undefined;
|
|
587
|
+
label?: string | undefined;
|
|
588
|
+
name?: string | undefined;
|
|
578
589
|
description?: string | undefined;
|
|
579
590
|
}>>>>;
|
|
580
591
|
/** OPTIONAL. Controls whether the claim must, may, or must not be selectively disclosed. */
|
|
@@ -862,18 +873,24 @@ declare const TypeMetadataFormatSchema: z.ZodObject<{
|
|
|
862
873
|
*/
|
|
863
874
|
locale: z.ZodOptional<z.ZodString>;
|
|
864
875
|
/** REQUIRED. Human-readable label for the claim. */
|
|
865
|
-
label: z.ZodString
|
|
876
|
+
label: z.ZodOptional<z.ZodString>;
|
|
877
|
+
/**
|
|
878
|
+
* Human-readable label for the claim.
|
|
879
|
+
* @deprecated - use `label` instead
|
|
880
|
+
*/
|
|
881
|
+
name: z.ZodOptional<z.ZodString>;
|
|
866
882
|
/** OPTIONAL. Description of the claim for end users. */
|
|
867
883
|
description: z.ZodOptional<z.ZodString>;
|
|
868
884
|
}, z.core.$loose>, z.ZodTransform<{
|
|
869
885
|
locale: string | undefined;
|
|
870
|
-
label: string;
|
|
886
|
+
label: string | undefined;
|
|
871
887
|
description?: string | undefined;
|
|
872
888
|
}, {
|
|
873
889
|
[x: string]: unknown;
|
|
874
|
-
label: string;
|
|
875
890
|
lang?: string | undefined;
|
|
876
891
|
locale?: string | undefined;
|
|
892
|
+
label?: string | undefined;
|
|
893
|
+
name?: string | undefined;
|
|
877
894
|
description?: string | undefined;
|
|
878
895
|
}>>>>;
|
|
879
896
|
/** OPTIONAL. Controls whether the claim must, may, or must not be selectively disclosed. */
|
|
@@ -915,7 +932,7 @@ type ResolvedTypeMetadata = {
|
|
|
915
932
|
};
|
|
916
933
|
type TypeMetadataFormat = z.infer<typeof TypeMetadataFormatSchema>;
|
|
917
934
|
|
|
918
|
-
type
|
|
935
|
+
type VCTFetcher = (uri: string, integrity?: string) => Promise<TypeMetadataFormat | undefined>;
|
|
919
936
|
|
|
920
937
|
type StatusListFetcher = (uri: string) => Promise<string>;
|
|
921
938
|
type StatusValidator = (status: number) => Promise<void>;
|
|
@@ -925,7 +942,7 @@ type StatusValidator = (status: number) => Promise<void>;
|
|
|
925
942
|
type SDJWTVCConfig = SDJWTConfig & {
|
|
926
943
|
statusListFetcher?: StatusListFetcher;
|
|
927
944
|
statusValidator?: StatusValidator;
|
|
928
|
-
vctFetcher?:
|
|
945
|
+
vctFetcher?: VCTFetcher;
|
|
929
946
|
statusVerifier?: Verifier;
|
|
930
947
|
loadTypeMetadataFormat?: boolean;
|
|
931
948
|
timeout?: number;
|
|
@@ -990,6 +1007,16 @@ declare class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
|
|
|
990
1007
|
* @param currentDate current time in seconds
|
|
991
1008
|
*/
|
|
992
1009
|
verify(encodedSDJwt: string, options?: VerifierOptions): Promise<VerificationResult>;
|
|
1010
|
+
/**
|
|
1011
|
+
* Safe verification that collects all errors instead of failing fast.
|
|
1012
|
+
* Returns a result object with either the verified data or an array of all errors.
|
|
1013
|
+
* This includes SD-JWT-VC specific validations like status and VCT metadata.
|
|
1014
|
+
*
|
|
1015
|
+
* @param encodedSDJwt - The encoded SD-JWT-VC to verify
|
|
1016
|
+
* @param options - Verification options
|
|
1017
|
+
* @returns A SafeVerifyResult containing either success data or collected errors
|
|
1018
|
+
*/
|
|
1019
|
+
safeVerify(encodedSDJwt: string, options?: VerifierOptions): Promise<SafeVerifyResult<VerificationResult>>;
|
|
993
1020
|
/**
|
|
994
1021
|
* 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.
|
|
995
1022
|
*
|
|
@@ -1073,6 +1100,7 @@ declare class SDJwtVcInstance extends SDJwtInstance<SdJwtVcPayload> {
|
|
|
1073
1100
|
* @param options
|
|
1074
1101
|
*/
|
|
1075
1102
|
private verifyStatus;
|
|
1103
|
+
config(newConfig: SDJWTVCConfig): void;
|
|
1076
1104
|
}
|
|
1077
1105
|
|
|
1078
|
-
export { type BackgroundImage, BackgroundImageSchema, type Claim, type ClaimDisplay, ClaimDisplaySchema, type ClaimPath, ClaimPathSchema, ClaimSchema, type ClaimSelectiveDisclosure, ClaimSelectiveDisclosureSchema, ColorSchemeSchema, ContrastSchema, type Display, DisplaySchema, type Logo, LogoSchema, OrientationSchema, type Rendering, RenderingSchema, type ResolvedTypeMetadata, type SDJWTVCConfig, type SDJWTVCStatusReference, SDJwtVcInstance, type SdJwtVcPayload, type SimpleRendering, SimpleRenderingSchema, type StatusListFetcher, type StatusValidator, type SvgTemplateProperties, SvgTemplatePropertiesSchema, type SvgTemplateRendering, SvgTemplateRenderingSchema, type TypeMetadataFormat, TypeMetadataFormatSchema, type
|
|
1106
|
+
export { type BackgroundImage, BackgroundImageSchema, type Claim, type ClaimDisplay, ClaimDisplaySchema, type ClaimPath, ClaimPathSchema, ClaimSchema, type ClaimSelectiveDisclosure, ClaimSelectiveDisclosureSchema, ColorSchemeSchema, ContrastSchema, type Display, DisplaySchema, type Logo, LogoSchema, OrientationSchema, type Rendering, RenderingSchema, type ResolvedTypeMetadata, type SDJWTVCConfig, type SDJWTVCStatusReference, SDJwtVcInstance, type SdJwtVcPayload, type SimpleRendering, SimpleRenderingSchema, type StatusListFetcher, type StatusValidator, type SvgTemplateProperties, SvgTemplatePropertiesSchema, type SvgTemplateRendering, SvgTemplateRenderingSchema, type TypeMetadataFormat, TypeMetadataFormatSchema, type VCTFetcher, type VerificationResult };
|
package/dist/index.js
CHANGED
|
@@ -101,9 +101,8 @@ __export(index_exports, {
|
|
|
101
101
|
module.exports = __toCommonJS(index_exports);
|
|
102
102
|
|
|
103
103
|
// src/sd-jwt-vc-instance.ts
|
|
104
|
+
var import_token_status_list = require("@owf/token-status-list");
|
|
104
105
|
var import_core = require("@sd-jwt/core");
|
|
105
|
-
var import_jwt_status_list = require("@sd-jwt/jwt-status-list");
|
|
106
|
-
var import_utils = require("@sd-jwt/utils");
|
|
107
106
|
var import_zod2 = __toESM(require("zod"));
|
|
108
107
|
|
|
109
108
|
// src/sd-jwt-vc-type-metadata-format.ts
|
|
@@ -205,16 +204,24 @@ var ClaimDisplaySchema = import_zod.z.looseObject({
|
|
|
205
204
|
*/
|
|
206
205
|
locale: import_zod.z.string().optional(),
|
|
207
206
|
/** REQUIRED. Human-readable label for the claim. */
|
|
208
|
-
label: import_zod.z.string(),
|
|
207
|
+
label: import_zod.z.string().optional(),
|
|
208
|
+
/**
|
|
209
|
+
* Human-readable label for the claim.
|
|
210
|
+
* @deprecated - use `label` instead
|
|
211
|
+
*/
|
|
212
|
+
name: import_zod.z.string().optional(),
|
|
209
213
|
/** OPTIONAL. Description of the claim for end users. */
|
|
210
214
|
description: import_zod.z.string().optional()
|
|
211
215
|
}).transform((_a) => {
|
|
212
|
-
var _b = _a, { lang, locale } = _b, rest = __objRest(_b, ["lang", "locale"]);
|
|
216
|
+
var _b = _a, { lang, name, label, locale } = _b, rest = __objRest(_b, ["lang", "name", "label", "locale"]);
|
|
213
217
|
return __spreadProps(__spreadValues({}, rest), {
|
|
214
|
-
locale: locale != null ? locale : lang
|
|
218
|
+
locale: locale != null ? locale : lang,
|
|
219
|
+
label: label != null ? label : name
|
|
215
220
|
});
|
|
216
221
|
}).refine(({ locale }) => locale !== void 0, {
|
|
217
|
-
message: "Either locale (preferred) or lang (
|
|
222
|
+
message: "Either locale (preferred) or lang (deprecated) MUST be defined on claim display entry."
|
|
223
|
+
}).refine(({ label }) => label !== void 0, {
|
|
224
|
+
message: "Either label (preferred) or name (deprecated) MUST be defined on claim display entry."
|
|
218
225
|
});
|
|
219
226
|
var ClaimSelectiveDisclosureSchema = import_zod.z.enum([
|
|
220
227
|
"always",
|
|
@@ -279,9 +286,11 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
279
286
|
validateReservedFields(disclosureFrame) {
|
|
280
287
|
if ((disclosureFrame == null ? void 0 : disclosureFrame._sd) && Array.isArray(disclosureFrame._sd) && disclosureFrame._sd.length > 0) {
|
|
281
288
|
const reservedNames = ["iss", "nbf", "exp", "cnf", "vct", "status"];
|
|
282
|
-
const reservedNamesInDisclosureFrame = disclosureFrame._sd.filter(
|
|
289
|
+
const reservedNamesInDisclosureFrame = disclosureFrame._sd.filter(
|
|
290
|
+
(key) => reservedNames.includes(String(key))
|
|
291
|
+
);
|
|
283
292
|
if (reservedNamesInDisclosureFrame.length > 0) {
|
|
284
|
-
throw new
|
|
293
|
+
throw new import_core.SDJWTException("Cannot disclose protected field");
|
|
285
294
|
}
|
|
286
295
|
}
|
|
287
296
|
}
|
|
@@ -321,7 +330,7 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
321
330
|
*/
|
|
322
331
|
statusValidator(status) {
|
|
323
332
|
return __async(this, null, function* () {
|
|
324
|
-
if (status !== 0) throw new
|
|
333
|
+
if (status !== 0) throw new import_core.SDJWTException("Status is not valid");
|
|
325
334
|
return Promise.resolve();
|
|
326
335
|
});
|
|
327
336
|
}
|
|
@@ -346,6 +355,96 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
346
355
|
return result;
|
|
347
356
|
});
|
|
348
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* Safe verification that collects all errors instead of failing fast.
|
|
360
|
+
* Returns a result object with either the verified data or an array of all errors.
|
|
361
|
+
* This includes SD-JWT-VC specific validations like status and VCT metadata.
|
|
362
|
+
*
|
|
363
|
+
* @param encodedSDJwt - The encoded SD-JWT-VC to verify
|
|
364
|
+
* @param options - Verification options
|
|
365
|
+
* @returns A SafeVerifyResult containing either success data or collected errors
|
|
366
|
+
*/
|
|
367
|
+
safeVerify(encodedSDJwt, options) {
|
|
368
|
+
return __async(this, null, function* () {
|
|
369
|
+
const errors = [];
|
|
370
|
+
const addError = (code, message, details) => {
|
|
371
|
+
errors.push({ code, message, details });
|
|
372
|
+
};
|
|
373
|
+
const baseResult = yield __superGet(_SDJwtVcInstance.prototype, this, "safeVerify").call(this, encodedSDJwt, options);
|
|
374
|
+
if (!baseResult.success) {
|
|
375
|
+
errors.push(...baseResult.errors);
|
|
376
|
+
}
|
|
377
|
+
let result;
|
|
378
|
+
if (baseResult.success) {
|
|
379
|
+
result = {
|
|
380
|
+
payload: baseResult.data.payload,
|
|
381
|
+
header: baseResult.data.header,
|
|
382
|
+
kb: baseResult.data.kb
|
|
383
|
+
};
|
|
384
|
+
} else {
|
|
385
|
+
try {
|
|
386
|
+
const { payload, header } = yield import_core.SDJwt.extractJwt(encodedSDJwt);
|
|
387
|
+
if (payload) {
|
|
388
|
+
result = {
|
|
389
|
+
payload,
|
|
390
|
+
header,
|
|
391
|
+
kb: void 0
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
} catch (e) {
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (result) {
|
|
398
|
+
try {
|
|
399
|
+
yield this.verifyStatus(result, options);
|
|
400
|
+
} catch (e) {
|
|
401
|
+
const error = (0, import_core.ensureError)(e);
|
|
402
|
+
const errorMessage = error.message;
|
|
403
|
+
if (errorMessage.includes("Status is not valid")) {
|
|
404
|
+
addError("STATUS_INVALID", errorMessage, error);
|
|
405
|
+
} else {
|
|
406
|
+
addError(
|
|
407
|
+
"STATUS_VERIFICATION_FAILED",
|
|
408
|
+
`Status verification failed: ${errorMessage}`,
|
|
409
|
+
error
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (this.userConfig.loadTypeMetadataFormat) {
|
|
414
|
+
try {
|
|
415
|
+
const resolvedTypeMetadata = yield this.fetchVct(result);
|
|
416
|
+
if (result) {
|
|
417
|
+
result.typeMetadata = resolvedTypeMetadata;
|
|
418
|
+
}
|
|
419
|
+
} catch (e) {
|
|
420
|
+
addError(
|
|
421
|
+
"VCT_VERIFICATION_FAILED",
|
|
422
|
+
`VCT verification failed: ${(0, import_core.ensureError)(e).message}`,
|
|
423
|
+
e
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (errors.length > 0) {
|
|
429
|
+
return { success: false, errors };
|
|
430
|
+
}
|
|
431
|
+
if (!result) {
|
|
432
|
+
return {
|
|
433
|
+
success: false,
|
|
434
|
+
errors: [
|
|
435
|
+
{
|
|
436
|
+
code: "INVALID_SD_JWT",
|
|
437
|
+
message: "Failed to construct verification result"
|
|
438
|
+
}
|
|
439
|
+
]
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
success: true,
|
|
444
|
+
data: result
|
|
445
|
+
};
|
|
446
|
+
});
|
|
447
|
+
}
|
|
349
448
|
/**
|
|
350
449
|
* 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.
|
|
351
450
|
*
|
|
@@ -358,7 +457,7 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
358
457
|
return __async(this, null, function* () {
|
|
359
458
|
const { payload, header } = yield import_core.SDJwt.extractJwt(encodedSDJwt);
|
|
360
459
|
if (!payload) {
|
|
361
|
-
throw new
|
|
460
|
+
throw new import_core.SDJWTException("JWT payload is missing");
|
|
362
461
|
}
|
|
363
462
|
const result = {
|
|
364
463
|
payload,
|
|
@@ -378,10 +477,10 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
378
477
|
if (!integrity) return;
|
|
379
478
|
const arrayBuffer = yield response.arrayBuffer();
|
|
380
479
|
const alg = integrity.split("-")[0];
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
);
|
|
480
|
+
if (!this.userConfig.hasher) {
|
|
481
|
+
throw new import_core.SDJWTException("Hasher not found");
|
|
482
|
+
}
|
|
483
|
+
const hashBuffer = yield this.userConfig.hasher(arrayBuffer, alg);
|
|
385
484
|
const integrityHash = integrity.split("-")[1];
|
|
386
485
|
const hash = Array.from(new Uint8Array(hashBuffer)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
387
486
|
if (hash !== integrityHash) {
|
|
@@ -412,7 +511,8 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
412
511
|
yield this.validateIntegrity(response.clone(), url, integrity);
|
|
413
512
|
const data = yield response.json();
|
|
414
513
|
return data;
|
|
415
|
-
} catch (
|
|
514
|
+
} catch (e) {
|
|
515
|
+
const error = (0, import_core.ensureError)(e);
|
|
416
516
|
if (error.name === "TimeoutError") {
|
|
417
517
|
throw new Error(`Request to ${url} timed out`);
|
|
418
518
|
}
|
|
@@ -463,7 +563,7 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
463
563
|
if (baseClaim.sd && extendingClaim.sd) {
|
|
464
564
|
if ((baseClaim.sd === "always" || baseClaim.sd === "never") && baseClaim.sd !== extendingClaim.sd) {
|
|
465
565
|
const pathStr = JSON.stringify(extendingClaim.path);
|
|
466
|
-
throw new
|
|
566
|
+
throw new import_core.SDJWTException(
|
|
467
567
|
`Cannot change 'sd' property from '${baseClaim.sd}' to '${extendingClaim.sd}' for claim at path ${pathStr}`
|
|
468
568
|
);
|
|
469
569
|
}
|
|
@@ -535,17 +635,17 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
535
635
|
var _a;
|
|
536
636
|
const maxDepth = (_a = this.userConfig.maxVctExtendsDepth) != null ? _a : 5;
|
|
537
637
|
if (maxDepth !== -1 && depth > maxDepth) {
|
|
538
|
-
throw new
|
|
638
|
+
throw new import_core.SDJWTException(
|
|
539
639
|
`Maximum VCT extends depth of ${maxDepth} exceeded`
|
|
540
640
|
);
|
|
541
641
|
}
|
|
542
642
|
if (!parentTypeMetadata.extends) {
|
|
543
|
-
throw new
|
|
643
|
+
throw new import_core.SDJWTException(
|
|
544
644
|
`Type metadata for vct '${parentTypeMetadata.vct}' has no 'extends' field. Unable to resolve extended type metadata document.`
|
|
545
645
|
);
|
|
546
646
|
}
|
|
547
647
|
if (visitedVcts.has(parentTypeMetadata.extends)) {
|
|
548
|
-
throw new
|
|
648
|
+
throw new import_core.SDJWTException(
|
|
549
649
|
`Circular dependency detected in VCT extends chain: ${parentTypeMetadata.extends}`
|
|
550
650
|
);
|
|
551
651
|
}
|
|
@@ -555,7 +655,7 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
555
655
|
parentTypeMetadata["extends#integrity"]
|
|
556
656
|
);
|
|
557
657
|
if (!extendedTypeMetadata) {
|
|
558
|
-
throw new
|
|
658
|
+
throw new import_core.SDJWTException(
|
|
559
659
|
`Resolving VCT extends value '${parentTypeMetadata.extends}' resulted in an undefined result.`
|
|
560
660
|
);
|
|
561
661
|
}
|
|
@@ -600,7 +700,7 @@ var SDJwtVcInstance = class _SDJwtVcInstance extends import_core.SDJwtInstance {
|
|
|
600
700
|
if (!data) return void 0;
|
|
601
701
|
const validated = TypeMetadataFormatSchema.safeParse(data);
|
|
602
702
|
if (!validated.success) {
|
|
603
|
-
throw new
|
|
703
|
+
throw new import_core.SDJWTException(
|
|
604
704
|
`Invalid VCT type metadata for vct '${vct}':
|
|
605
705
|
${import_zod2.default.prettifyError(validated.error)}`
|
|
606
706
|
);
|
|
@@ -623,16 +723,19 @@ ${import_zod2.default.prettifyError(validated.error)}`
|
|
|
623
723
|
result.payload.status.status_list.uri
|
|
624
724
|
);
|
|
625
725
|
const slJWT = import_core.Jwt.fromEncode(statusListJWT);
|
|
726
|
+
if (!this.userConfig.verifier || !this.userConfig.statusVerifier) {
|
|
727
|
+
throw new import_core.SDJWTException("Verifier not found for status list JWT");
|
|
728
|
+
}
|
|
626
729
|
yield slJWT.verify(
|
|
627
730
|
(_b = this.userConfig.statusVerifier) != null ? _b : this.userConfig.verifier,
|
|
628
731
|
options
|
|
629
732
|
).catch((err) => {
|
|
630
|
-
throw new
|
|
733
|
+
throw new import_token_status_list.SLException(
|
|
631
734
|
`Status List JWT verification failed: ${err.message}`,
|
|
632
735
|
err.details
|
|
633
736
|
);
|
|
634
737
|
});
|
|
635
|
-
const statusList = (0,
|
|
738
|
+
const statusList = (0, import_token_status_list.getListFromStatusListJWT)(statusListJWT);
|
|
636
739
|
const status = statusList.getStatus(
|
|
637
740
|
result.payload.status.status_list.idx
|
|
638
741
|
);
|
|
@@ -642,6 +745,9 @@ ${import_zod2.default.prettifyError(validated.error)}`
|
|
|
642
745
|
}
|
|
643
746
|
});
|
|
644
747
|
}
|
|
748
|
+
config(newConfig) {
|
|
749
|
+
super.config(newConfig);
|
|
750
|
+
}
|
|
645
751
|
};
|
|
646
752
|
// Annotate the CommonJS export names for ESM import in node:
|
|
647
753
|
0 && (module.exports = {
|