@sd-jwt/core 0.12.1-next.0 → 0.12.1-next.2
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 +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +31 -7
- package/dist/index.mjs +31 -7
- package/package.json +7 -7
- package/src/index.ts +12 -7
- package/src/jwt.ts +45 -1
- package/src/test/index.spec.ts +15 -15
- package/src/test/jwt.spec.ts +105 -0
- package/test/app-e2e.spec.ts +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -8,6 +8,19 @@ type JwtData<Header extends Record<string, unknown>, Payload extends Record<stri
|
|
|
8
8
|
signature?: Base64urlString;
|
|
9
9
|
encoded?: string;
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Options for the JWT verifier
|
|
13
|
+
*/
|
|
14
|
+
type VerifierOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* current time in seconds since epoch
|
|
17
|
+
*/
|
|
18
|
+
currentDate?: number;
|
|
19
|
+
/**
|
|
20
|
+
* allowed skew for the current time in seconds. Positive value that will lower the iat and nbf checks, and increase the exp check.
|
|
21
|
+
*/
|
|
22
|
+
skewSeconds?: number;
|
|
23
|
+
};
|
|
11
24
|
declare class Jwt<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>> {
|
|
12
25
|
header?: Header;
|
|
13
26
|
payload?: Payload;
|
|
@@ -25,7 +38,14 @@ declare class Jwt<Header extends Record<string, unknown> = Record<string, unknow
|
|
|
25
38
|
protected getUnsignedToken(): string;
|
|
26
39
|
sign(signer: Signer): Promise<string>;
|
|
27
40
|
encodeJwt(): string;
|
|
28
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Verify the JWT using the provided verifier function.
|
|
43
|
+
* It checks the signature and validates the iat, nbf, and exp claims if they are present.
|
|
44
|
+
* @param verifier
|
|
45
|
+
* @param options - Options for verification, such as current date and skew seconds
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
verify(verifier: Verifier, options?: VerifierOptions): Promise<{
|
|
29
49
|
payload: Payload | undefined;
|
|
30
50
|
header: Header | undefined;
|
|
31
51
|
}>;
|
|
@@ -197,7 +217,14 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
197
217
|
};
|
|
198
218
|
}>;
|
|
199
219
|
private calculateSDHash;
|
|
200
|
-
|
|
220
|
+
/**
|
|
221
|
+
* This function is for validating the SD JWT
|
|
222
|
+
* Checking signature, if provided the iat and exp when provided and return its the claims
|
|
223
|
+
* @param encodedSDJwt
|
|
224
|
+
* @param options
|
|
225
|
+
* @returns
|
|
226
|
+
*/
|
|
227
|
+
validate(encodedSDJwt: string, options?: VerifierOptions): Promise<{
|
|
201
228
|
payload: unknown;
|
|
202
229
|
header: Record<string, unknown> | undefined;
|
|
203
230
|
}>;
|
|
@@ -259,4 +286,4 @@ declare class SDJwtGeneralJSONInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
259
286
|
getClaims(generalSdjwt: GeneralJSON): Promise<unknown>;
|
|
260
287
|
}
|
|
261
288
|
|
|
262
|
-
export { FlattenJSON, type FlattenJSONData, type FlattenJSONSerialized, GeneralJSON, type GeneralJSONData, type GeneralJSONSerialized, Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtGeneralJSONInstance, SDJwtInstance, type SdJwtPayload, createDecoy, listKeys, pack };
|
|
289
|
+
export { FlattenJSON, type FlattenJSONData, type FlattenJSONSerialized, GeneralJSON, type GeneralJSONData, type GeneralJSONSerialized, Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtGeneralJSONInstance, SDJwtInstance, type SdJwtPayload, type VerifierOptions, createDecoy, listKeys, pack };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,19 @@ type JwtData<Header extends Record<string, unknown>, Payload extends Record<stri
|
|
|
8
8
|
signature?: Base64urlString;
|
|
9
9
|
encoded?: string;
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Options for the JWT verifier
|
|
13
|
+
*/
|
|
14
|
+
type VerifierOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* current time in seconds since epoch
|
|
17
|
+
*/
|
|
18
|
+
currentDate?: number;
|
|
19
|
+
/**
|
|
20
|
+
* allowed skew for the current time in seconds. Positive value that will lower the iat and nbf checks, and increase the exp check.
|
|
21
|
+
*/
|
|
22
|
+
skewSeconds?: number;
|
|
23
|
+
};
|
|
11
24
|
declare class Jwt<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>> {
|
|
12
25
|
header?: Header;
|
|
13
26
|
payload?: Payload;
|
|
@@ -25,7 +38,14 @@ declare class Jwt<Header extends Record<string, unknown> = Record<string, unknow
|
|
|
25
38
|
protected getUnsignedToken(): string;
|
|
26
39
|
sign(signer: Signer): Promise<string>;
|
|
27
40
|
encodeJwt(): string;
|
|
28
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Verify the JWT using the provided verifier function.
|
|
43
|
+
* It checks the signature and validates the iat, nbf, and exp claims if they are present.
|
|
44
|
+
* @param verifier
|
|
45
|
+
* @param options - Options for verification, such as current date and skew seconds
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
verify(verifier: Verifier, options?: VerifierOptions): Promise<{
|
|
29
49
|
payload: Payload | undefined;
|
|
30
50
|
header: Header | undefined;
|
|
31
51
|
}>;
|
|
@@ -197,7 +217,14 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
197
217
|
};
|
|
198
218
|
}>;
|
|
199
219
|
private calculateSDHash;
|
|
200
|
-
|
|
220
|
+
/**
|
|
221
|
+
* This function is for validating the SD JWT
|
|
222
|
+
* Checking signature, if provided the iat and exp when provided and return its the claims
|
|
223
|
+
* @param encodedSDJwt
|
|
224
|
+
* @param options
|
|
225
|
+
* @returns
|
|
226
|
+
*/
|
|
227
|
+
validate(encodedSDJwt: string, options?: VerifierOptions): Promise<{
|
|
201
228
|
payload: unknown;
|
|
202
229
|
header: Record<string, unknown> | undefined;
|
|
203
230
|
}>;
|
|
@@ -259,4 +286,4 @@ declare class SDJwtGeneralJSONInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
259
286
|
getClaims(generalSdjwt: GeneralJSON): Promise<unknown>;
|
|
260
287
|
}
|
|
261
288
|
|
|
262
|
-
export { FlattenJSON, type FlattenJSONData, type FlattenJSONSerialized, GeneralJSON, type GeneralJSONData, type GeneralJSONSerialized, Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtGeneralJSONInstance, SDJwtInstance, type SdJwtPayload, createDecoy, listKeys, pack };
|
|
289
|
+
export { FlattenJSON, type FlattenJSONData, type FlattenJSONSerialized, GeneralJSON, type GeneralJSONData, type GeneralJSONSerialized, Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtGeneralJSONInstance, SDJwtInstance, type SdJwtPayload, type VerifierOptions, createDecoy, listKeys, pack };
|
package/dist/index.js
CHANGED
|
@@ -143,8 +143,27 @@ var Jwt = class _Jwt {
|
|
|
143
143
|
this.encoded = compact;
|
|
144
144
|
return compact;
|
|
145
145
|
}
|
|
146
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Verify the JWT using the provided verifier function.
|
|
148
|
+
* It checks the signature and validates the iat, nbf, and exp claims if they are present.
|
|
149
|
+
* @param verifier
|
|
150
|
+
* @param options - Options for verification, such as current date and skew seconds
|
|
151
|
+
* @returns
|
|
152
|
+
*/
|
|
153
|
+
verify(verifier, options) {
|
|
147
154
|
return __async(this, null, function* () {
|
|
155
|
+
var _a, _b, _c, _d;
|
|
156
|
+
const skew = (options == null ? void 0 : options.skewSeconds) ? options.skewSeconds : 0;
|
|
157
|
+
const currentDate = (_a = options == null ? void 0 : options.currentDate) != null ? _a : Math.floor(Date.now() / 1e3);
|
|
158
|
+
if (((_b = this.payload) == null ? void 0 : _b.iat) && this.payload.iat - skew > currentDate) {
|
|
159
|
+
throw new import_utils.SDJWTException("Verify Error: JWT is not yet valid");
|
|
160
|
+
}
|
|
161
|
+
if (((_c = this.payload) == null ? void 0 : _c.nbf) && this.payload.nbf - skew > currentDate) {
|
|
162
|
+
throw new import_utils.SDJWTException("Verify Error: JWT is not yet valid");
|
|
163
|
+
}
|
|
164
|
+
if (((_d = this.payload) == null ? void 0 : _d.exp) && this.payload.exp + skew < currentDate) {
|
|
165
|
+
throw new import_utils.SDJWTException("Verify Error: JWT is expired");
|
|
166
|
+
}
|
|
148
167
|
if (!this.signature) {
|
|
149
168
|
throw new import_utils.SDJWTException("Verify Error: no signature in JWT");
|
|
150
169
|
}
|
|
@@ -655,12 +674,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
655
674
|
return jwt;
|
|
656
675
|
});
|
|
657
676
|
}
|
|
658
|
-
VerifyJwt(jwt) {
|
|
677
|
+
VerifyJwt(jwt, options) {
|
|
659
678
|
return __async(this, null, function* () {
|
|
660
679
|
if (!this.userConfig.verifier) {
|
|
661
680
|
throw new import_utils7.SDJWTException("Verifier not found");
|
|
662
681
|
}
|
|
663
|
-
return jwt.verify(this.userConfig.verifier);
|
|
682
|
+
return jwt.verify(this.userConfig.verifier, options);
|
|
664
683
|
});
|
|
665
684
|
}
|
|
666
685
|
issue(payload, disclosureFrame, options) {
|
|
@@ -804,9 +823,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
804
823
|
return sdHashStr;
|
|
805
824
|
});
|
|
806
825
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
826
|
+
/**
|
|
827
|
+
* This function is for validating the SD JWT
|
|
828
|
+
* Checking signature, if provided the iat and exp when provided and return its the claims
|
|
829
|
+
* @param encodedSDJwt
|
|
830
|
+
* @param options
|
|
831
|
+
* @returns
|
|
832
|
+
*/
|
|
833
|
+
validate(encodedSDJwt, options) {
|
|
810
834
|
return __async(this, null, function* () {
|
|
811
835
|
if (!this.userConfig.hasher) {
|
|
812
836
|
throw new import_utils7.SDJWTException("Hasher not found");
|
|
@@ -816,7 +840,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
816
840
|
if (!sdjwt.jwt) {
|
|
817
841
|
throw new import_utils7.SDJWTException("Invalid SD JWT");
|
|
818
842
|
}
|
|
819
|
-
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt);
|
|
843
|
+
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt, options);
|
|
820
844
|
const claims = yield sdjwt.getClaims(hasher);
|
|
821
845
|
return { payload: claims, header: verifiedPayloads.header };
|
|
822
846
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -118,8 +118,27 @@ var Jwt = class _Jwt {
|
|
|
118
118
|
this.encoded = compact;
|
|
119
119
|
return compact;
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Verify the JWT using the provided verifier function.
|
|
123
|
+
* It checks the signature and validates the iat, nbf, and exp claims if they are present.
|
|
124
|
+
* @param verifier
|
|
125
|
+
* @param options - Options for verification, such as current date and skew seconds
|
|
126
|
+
* @returns
|
|
127
|
+
*/
|
|
128
|
+
verify(verifier, options) {
|
|
122
129
|
return __async(this, null, function* () {
|
|
130
|
+
var _a, _b, _c, _d;
|
|
131
|
+
const skew = (options == null ? void 0 : options.skewSeconds) ? options.skewSeconds : 0;
|
|
132
|
+
const currentDate = (_a = options == null ? void 0 : options.currentDate) != null ? _a : Math.floor(Date.now() / 1e3);
|
|
133
|
+
if (((_b = this.payload) == null ? void 0 : _b.iat) && this.payload.iat - skew > currentDate) {
|
|
134
|
+
throw new SDJWTException("Verify Error: JWT is not yet valid");
|
|
135
|
+
}
|
|
136
|
+
if (((_c = this.payload) == null ? void 0 : _c.nbf) && this.payload.nbf - skew > currentDate) {
|
|
137
|
+
throw new SDJWTException("Verify Error: JWT is not yet valid");
|
|
138
|
+
}
|
|
139
|
+
if (((_d = this.payload) == null ? void 0 : _d.exp) && this.payload.exp + skew < currentDate) {
|
|
140
|
+
throw new SDJWTException("Verify Error: JWT is expired");
|
|
141
|
+
}
|
|
123
142
|
if (!this.signature) {
|
|
124
143
|
throw new SDJWTException("Verify Error: no signature in JWT");
|
|
125
144
|
}
|
|
@@ -640,12 +659,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
640
659
|
return jwt;
|
|
641
660
|
});
|
|
642
661
|
}
|
|
643
|
-
VerifyJwt(jwt) {
|
|
662
|
+
VerifyJwt(jwt, options) {
|
|
644
663
|
return __async(this, null, function* () {
|
|
645
664
|
if (!this.userConfig.verifier) {
|
|
646
665
|
throw new SDJWTException6("Verifier not found");
|
|
647
666
|
}
|
|
648
|
-
return jwt.verify(this.userConfig.verifier);
|
|
667
|
+
return jwt.verify(this.userConfig.verifier, options);
|
|
649
668
|
});
|
|
650
669
|
}
|
|
651
670
|
issue(payload, disclosureFrame, options) {
|
|
@@ -789,9 +808,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
789
808
|
return sdHashStr;
|
|
790
809
|
});
|
|
791
810
|
}
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
811
|
+
/**
|
|
812
|
+
* This function is for validating the SD JWT
|
|
813
|
+
* Checking signature, if provided the iat and exp when provided and return its the claims
|
|
814
|
+
* @param encodedSDJwt
|
|
815
|
+
* @param options
|
|
816
|
+
* @returns
|
|
817
|
+
*/
|
|
818
|
+
validate(encodedSDJwt, options) {
|
|
795
819
|
return __async(this, null, function* () {
|
|
796
820
|
if (!this.userConfig.hasher) {
|
|
797
821
|
throw new SDJWTException6("Hasher not found");
|
|
@@ -801,7 +825,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
801
825
|
if (!sdjwt.jwt) {
|
|
802
826
|
throw new SDJWTException6("Invalid SD JWT");
|
|
803
827
|
}
|
|
804
|
-
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt);
|
|
828
|
+
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt, options);
|
|
805
829
|
const claims = yield sdjwt.getClaims(hasher);
|
|
806
830
|
return { payload: claims, header: verifiedPayloads.header };
|
|
807
831
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/core",
|
|
3
|
-
"version": "0.12.1-next.
|
|
3
|
+
"version": "0.12.1-next.2+1eefb26",
|
|
4
4
|
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
},
|
|
39
39
|
"license": "Apache-2.0",
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@sd-jwt/crypto-nodejs": "0.12.1-next.
|
|
41
|
+
"@sd-jwt/crypto-nodejs": "0.12.1-next.2+1eefb26"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@sd-jwt/decode": "0.12.1-next.
|
|
45
|
-
"@sd-jwt/present": "0.12.1-next.
|
|
46
|
-
"@sd-jwt/types": "0.12.1-next.
|
|
47
|
-
"@sd-jwt/utils": "0.12.1-next.
|
|
44
|
+
"@sd-jwt/decode": "0.12.1-next.2+1eefb26",
|
|
45
|
+
"@sd-jwt/present": "0.12.1-next.2+1eefb26",
|
|
46
|
+
"@sd-jwt/types": "0.12.1-next.2+1eefb26",
|
|
47
|
+
"@sd-jwt/utils": "0.12.1-next.2+1eefb26"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"esm"
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "1eefb262c40ea23e999cdef6e75222e5b4df1e2c"
|
|
66
66
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
SDJWTException,
|
|
5
5
|
uint8ArrayToBase64Url,
|
|
6
6
|
} from '@sd-jwt/utils';
|
|
7
|
-
import { Jwt } from './jwt';
|
|
7
|
+
import { Jwt, type VerifierOptions } from './jwt';
|
|
8
8
|
import { KBJwt } from './kbjwt';
|
|
9
9
|
import { SDJwt, pack } from './sdjwt';
|
|
10
10
|
import {
|
|
@@ -86,11 +86,11 @@ export class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
86
86
|
return jwt;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
private async VerifyJwt(jwt: Jwt) {
|
|
89
|
+
private async VerifyJwt(jwt: Jwt, options?: VerifierOptions) {
|
|
90
90
|
if (!this.userConfig.verifier) {
|
|
91
91
|
throw new SDJWTException('Verifier not found');
|
|
92
92
|
}
|
|
93
|
-
return jwt.verify(this.userConfig.verifier);
|
|
93
|
+
return jwt.verify(this.userConfig.verifier, options);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
public async issue<Payload extends ExtendedPayload>(
|
|
@@ -273,9 +273,14 @@ export class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
273
273
|
return sdHashStr;
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
276
|
+
/**
|
|
277
|
+
* This function is for validating the SD JWT
|
|
278
|
+
* Checking signature, if provided the iat and exp when provided and return its the claims
|
|
279
|
+
* @param encodedSDJwt
|
|
280
|
+
* @param options
|
|
281
|
+
* @returns
|
|
282
|
+
*/
|
|
283
|
+
public async validate(encodedSDJwt: string, options?: VerifierOptions) {
|
|
279
284
|
if (!this.userConfig.hasher) {
|
|
280
285
|
throw new SDJWTException('Hasher not found');
|
|
281
286
|
}
|
|
@@ -286,7 +291,7 @@ export class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
286
291
|
throw new SDJWTException('Invalid SD JWT');
|
|
287
292
|
}
|
|
288
293
|
|
|
289
|
-
const verifiedPayloads = await this.VerifyJwt(sdjwt.jwt);
|
|
294
|
+
const verifiedPayloads = await this.VerifyJwt(sdjwt.jwt, options);
|
|
290
295
|
const claims = await sdjwt.getClaims(hasher);
|
|
291
296
|
return { payload: claims, header: verifiedPayloads.header };
|
|
292
297
|
}
|
package/src/jwt.ts
CHANGED
|
@@ -12,6 +12,21 @@ export type JwtData<
|
|
|
12
12
|
encoded?: string;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Options for the JWT verifier
|
|
17
|
+
*/
|
|
18
|
+
export type VerifierOptions = {
|
|
19
|
+
/**
|
|
20
|
+
* current time in seconds since epoch
|
|
21
|
+
*/
|
|
22
|
+
currentDate?: number;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* allowed skew for the current time in seconds. Positive value that will lower the iat and nbf checks, and increase the exp check.
|
|
26
|
+
*/
|
|
27
|
+
skewSeconds?: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
15
30
|
// This class is used to create and verify JWT
|
|
16
31
|
// Contains header, payload, and signature
|
|
17
32
|
export class Jwt<
|
|
@@ -113,7 +128,36 @@ export class Jwt<
|
|
|
113
128
|
return compact;
|
|
114
129
|
}
|
|
115
130
|
|
|
116
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Verify the JWT using the provided verifier function.
|
|
133
|
+
* It checks the signature and validates the iat, nbf, and exp claims if they are present.
|
|
134
|
+
* @param verifier
|
|
135
|
+
* @param options - Options for verification, such as current date and skew seconds
|
|
136
|
+
* @returns
|
|
137
|
+
*/
|
|
138
|
+
public async verify(verifier: Verifier, options?: VerifierOptions) {
|
|
139
|
+
const skew = options?.skewSeconds ? options.skewSeconds : 0;
|
|
140
|
+
const currentDate = options?.currentDate ?? Math.floor(Date.now() / 1000);
|
|
141
|
+
if (
|
|
142
|
+
this.payload?.iat &&
|
|
143
|
+
(this.payload.iat as number) - skew > currentDate
|
|
144
|
+
) {
|
|
145
|
+
throw new SDJWTException('Verify Error: JWT is not yet valid');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (
|
|
149
|
+
this.payload?.nbf &&
|
|
150
|
+
(this.payload.nbf as number) - skew > currentDate
|
|
151
|
+
) {
|
|
152
|
+
throw new SDJWTException('Verify Error: JWT is not yet valid');
|
|
153
|
+
}
|
|
154
|
+
if (
|
|
155
|
+
this.payload?.exp &&
|
|
156
|
+
(this.payload.exp as number) + skew < currentDate
|
|
157
|
+
) {
|
|
158
|
+
throw new SDJWTException('Verify Error: JWT is expired');
|
|
159
|
+
}
|
|
160
|
+
|
|
117
161
|
if (!this.signature) {
|
|
118
162
|
throw new SDJWTException('Verify Error: no signature in JWT');
|
|
119
163
|
}
|
package/src/test/index.spec.ts
CHANGED
|
@@ -49,7 +49,7 @@ describe('index', () => {
|
|
|
49
49
|
{
|
|
50
50
|
foo: 'bar',
|
|
51
51
|
iss: 'Issuer',
|
|
52
|
-
iat:
|
|
52
|
+
iat: Math.floor(Date.now() / 1000),
|
|
53
53
|
vct: '',
|
|
54
54
|
},
|
|
55
55
|
{
|
|
@@ -89,7 +89,7 @@ describe('index', () => {
|
|
|
89
89
|
{
|
|
90
90
|
foo: 'bar',
|
|
91
91
|
iss: 'Issuer',
|
|
92
|
-
iat:
|
|
92
|
+
iat: Math.floor(Date.now() / 1000),
|
|
93
93
|
vct: '',
|
|
94
94
|
},
|
|
95
95
|
{
|
|
@@ -124,7 +124,7 @@ describe('index', () => {
|
|
|
124
124
|
{
|
|
125
125
|
foo: 'bar',
|
|
126
126
|
iss: 'Issuer',
|
|
127
|
-
iat:
|
|
127
|
+
iat: Math.floor(Date.now() / 1000),
|
|
128
128
|
vct: '',
|
|
129
129
|
},
|
|
130
130
|
{
|
|
@@ -165,7 +165,7 @@ describe('index', () => {
|
|
|
165
165
|
{
|
|
166
166
|
foo: 'bar',
|
|
167
167
|
iss: 'Issuer',
|
|
168
|
-
iat:
|
|
168
|
+
iat: Math.floor(Date.now() / 1000),
|
|
169
169
|
vct: '',
|
|
170
170
|
},
|
|
171
171
|
{
|
|
@@ -239,7 +239,7 @@ describe('index', () => {
|
|
|
239
239
|
const credential = await sdjwt.issue(
|
|
240
240
|
{
|
|
241
241
|
foo: 'bar',
|
|
242
|
-
iat:
|
|
242
|
+
iat: Math.floor(Date.now() / 1000),
|
|
243
243
|
cnf: {
|
|
244
244
|
jwk: await exportJWK(publicKey),
|
|
245
245
|
},
|
|
@@ -274,7 +274,7 @@ describe('index', () => {
|
|
|
274
274
|
{
|
|
275
275
|
foo: 'bar',
|
|
276
276
|
iss: 'Issuer',
|
|
277
|
-
iat:
|
|
277
|
+
iat: Math.floor(Date.now() / 1000),
|
|
278
278
|
vct: '',
|
|
279
279
|
},
|
|
280
280
|
{
|
|
@@ -297,7 +297,7 @@ describe('index', () => {
|
|
|
297
297
|
{
|
|
298
298
|
foo: 'bar',
|
|
299
299
|
iss: 'Issuer',
|
|
300
|
-
iat:
|
|
300
|
+
iat: Math.floor(Date.now() / 1000),
|
|
301
301
|
vct: '',
|
|
302
302
|
},
|
|
303
303
|
{
|
|
@@ -321,7 +321,7 @@ describe('index', () => {
|
|
|
321
321
|
{
|
|
322
322
|
foo: 'bar',
|
|
323
323
|
iss: 'Issuer',
|
|
324
|
-
iat:
|
|
324
|
+
iat: Math.floor(Date.now() / 1000),
|
|
325
325
|
vct: '',
|
|
326
326
|
},
|
|
327
327
|
{
|
|
@@ -351,7 +351,7 @@ describe('index', () => {
|
|
|
351
351
|
{
|
|
352
352
|
foo: 'bar',
|
|
353
353
|
iss: 'Issuer',
|
|
354
|
-
iat:
|
|
354
|
+
iat: Math.floor(Date.now() / 1000),
|
|
355
355
|
vct: '',
|
|
356
356
|
},
|
|
357
357
|
{
|
|
@@ -395,7 +395,7 @@ describe('index', () => {
|
|
|
395
395
|
{
|
|
396
396
|
foo: 'bar',
|
|
397
397
|
iss: 'Issuer',
|
|
398
|
-
iat:
|
|
398
|
+
iat: Math.floor(Date.now() / 1000),
|
|
399
399
|
vct: '',
|
|
400
400
|
},
|
|
401
401
|
{
|
|
@@ -437,7 +437,7 @@ describe('index', () => {
|
|
|
437
437
|
{
|
|
438
438
|
foo: 'bar',
|
|
439
439
|
iss: 'Issuer',
|
|
440
|
-
iat:
|
|
440
|
+
iat: Math.floor(Date.now() / 1000),
|
|
441
441
|
vct: '',
|
|
442
442
|
},
|
|
443
443
|
{
|
|
@@ -480,7 +480,7 @@ describe('index', () => {
|
|
|
480
480
|
{
|
|
481
481
|
foo: 'bar',
|
|
482
482
|
iss: 'Issuer',
|
|
483
|
-
iat:
|
|
483
|
+
iat: Math.floor(Date.now() / 1000),
|
|
484
484
|
vct: '',
|
|
485
485
|
},
|
|
486
486
|
{
|
|
@@ -518,7 +518,7 @@ describe('index', () => {
|
|
|
518
518
|
{
|
|
519
519
|
foo: 'bar',
|
|
520
520
|
iss: 'Issuer',
|
|
521
|
-
iat:
|
|
521
|
+
iat: Math.floor(Date.now() / 1000),
|
|
522
522
|
vct: '',
|
|
523
523
|
},
|
|
524
524
|
{
|
|
@@ -547,7 +547,7 @@ describe('index', () => {
|
|
|
547
547
|
{
|
|
548
548
|
foo: 'bar',
|
|
549
549
|
iss: 'Issuer',
|
|
550
|
-
iat:
|
|
550
|
+
iat: Math.floor(Date.now() / 1000),
|
|
551
551
|
vct: '',
|
|
552
552
|
},
|
|
553
553
|
{
|
|
@@ -573,7 +573,7 @@ describe('index', () => {
|
|
|
573
573
|
{
|
|
574
574
|
foo: 'bar',
|
|
575
575
|
iss: 'Issuer',
|
|
576
|
-
iat:
|
|
576
|
+
iat: Math.floor(Date.now() / 1000),
|
|
577
577
|
vct: '',
|
|
578
578
|
},
|
|
579
579
|
{
|
package/src/test/jwt.spec.ts
CHANGED
|
@@ -199,4 +199,109 @@ describe('JWT', () => {
|
|
|
199
199
|
expect(e).toBeInstanceOf(SDJWTException);
|
|
200
200
|
}
|
|
201
201
|
});
|
|
202
|
+
|
|
203
|
+
test('verify with issuance date in the future', async () => {
|
|
204
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
205
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
206
|
+
return Crypto.verify(
|
|
207
|
+
null,
|
|
208
|
+
Buffer.from(data),
|
|
209
|
+
publicKey,
|
|
210
|
+
Buffer.from(sig, 'base64url'),
|
|
211
|
+
);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const jwt = new Jwt({
|
|
215
|
+
header: { alg: 'EdDSA' },
|
|
216
|
+
payload: { iat: Math.floor(Date.now() / 1000) + 100 },
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
await jwt.verify(testVerifier);
|
|
221
|
+
} catch (e: unknown) {
|
|
222
|
+
expect(e).toBeInstanceOf(SDJWTException);
|
|
223
|
+
expect((e as SDJWTException).message).toBe(
|
|
224
|
+
'Verify Error: JWT is not yet valid',
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('verify with not before in the future', async () => {
|
|
230
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
231
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
232
|
+
return Crypto.verify(
|
|
233
|
+
null,
|
|
234
|
+
Buffer.from(data),
|
|
235
|
+
publicKey,
|
|
236
|
+
Buffer.from(sig, 'base64url'),
|
|
237
|
+
);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const jwt = new Jwt({
|
|
241
|
+
header: { alg: 'EdDSA' },
|
|
242
|
+
payload: { nbf: Math.floor(Date.now() / 1000) + 100 },
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
await jwt.verify(testVerifier);
|
|
247
|
+
} catch (e: unknown) {
|
|
248
|
+
expect(e).toBeInstanceOf(SDJWTException);
|
|
249
|
+
expect((e as SDJWTException).message).toBe(
|
|
250
|
+
'Verify Error: JWT is not yet valid',
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('verify with expired', async () => {
|
|
256
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
257
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
258
|
+
return Crypto.verify(
|
|
259
|
+
null,
|
|
260
|
+
Buffer.from(data),
|
|
261
|
+
publicKey,
|
|
262
|
+
Buffer.from(sig, 'base64url'),
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const jwt = new Jwt({
|
|
267
|
+
header: { alg: 'EdDSA' },
|
|
268
|
+
payload: { exp: Math.floor(Date.now() / 1000) },
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
await jwt.verify(testVerifier, {
|
|
273
|
+
currentDate: Math.floor(Date.now() / 1000) + 100,
|
|
274
|
+
});
|
|
275
|
+
} catch (e: unknown) {
|
|
276
|
+
expect(e).toBeInstanceOf(SDJWTException);
|
|
277
|
+
expect((e as SDJWTException).message).toBe(
|
|
278
|
+
'Verify Error: JWT is expired',
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test('verify with skew', async () => {
|
|
284
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
285
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
286
|
+
return Crypto.verify(
|
|
287
|
+
null,
|
|
288
|
+
Buffer.from(data),
|
|
289
|
+
publicKey,
|
|
290
|
+
Buffer.from(sig, 'base64url'),
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const jwt = new Jwt({
|
|
295
|
+
header: { alg: 'EdDSA' },
|
|
296
|
+
payload: { exp: Math.floor(Date.now() / 1000) - 1 },
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const testSigner: Signer = async (data: string) => {
|
|
300
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
301
|
+
return Buffer.from(sig).toString('base64url');
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
await jwt.sign(testSigner);
|
|
305
|
+
await jwt.verify(testVerifier, { skewSeconds: 2 });
|
|
306
|
+
});
|
|
202
307
|
});
|
package/test/app-e2e.spec.ts
CHANGED
|
@@ -224,7 +224,7 @@ async function JSONtest(filename: string) {
|
|
|
224
224
|
payload: test.claims,
|
|
225
225
|
});
|
|
226
226
|
|
|
227
|
-
const presentedSDJwt = await sdjwt.present<typeof claims>(
|
|
227
|
+
const presentedSDJwt = await sdjwt.present<typeof test.claims>(
|
|
228
228
|
encodedSdjwt,
|
|
229
229
|
test.presentationFrames,
|
|
230
230
|
);
|