jose 6.0.8 → 6.0.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 +1 -1
- package/dist/types/index.d.ts +1 -2
- package/dist/types/jwe/compact/encrypt.d.ts +6 -2
- package/dist/types/jwe/flattened/encrypt.d.ts +6 -9
- package/dist/types/jwe/general/encrypt.d.ts +9 -9
- package/dist/types/jwks/remote.d.ts +10 -1
- package/dist/types/jws/compact/sign.d.ts +6 -2
- package/dist/types/jws/flattened/sign.d.ts +6 -4
- package/dist/types/jws/general/sign.d.ts +9 -6
- package/dist/types/jwt/encrypt.d.ts +15 -9
- package/dist/types/jwt/sign.d.ts +15 -3
- package/dist/types/jwt/unsecured.d.ts +15 -2
- package/dist/types/types.d.ts +107 -0
- package/dist/types/util/errors.d.ts +15 -1
- package/dist/webapi/jwe/compact/encrypt.js +7 -7
- package/dist/webapi/jwe/flattened/encrypt.js +44 -44
- package/dist/webapi/jwe/general/encrypt.js +40 -40
- package/dist/webapi/jwks/local.js +11 -14
- package/dist/webapi/jwks/remote.js +52 -46
- package/dist/webapi/jws/compact/sign.js +4 -4
- package/dist/webapi/jws/flattened/sign.js +20 -20
- package/dist/webapi/jws/general/sign.js +13 -13
- package/dist/webapi/jwt/decrypt.js +2 -2
- package/dist/webapi/jwt/encrypt.js +70 -37
- package/dist/webapi/jwt/sign.js +41 -10
- package/dist/webapi/jwt/unsecured.js +36 -5
- package/dist/webapi/jwt/verify.js +2 -2
- package/dist/webapi/lib/jwt_claims_set.js +78 -2
- package/package.json +1 -1
- package/dist/types/jwt/produce.d.ts +0 -104
- package/dist/webapi/jwt/produce.js +0 -76
|
@@ -7,44 +7,44 @@ import checkKeyType from '../../lib/check_key_type.js';
|
|
|
7
7
|
import validateCrit from '../../lib/validate_crit.js';
|
|
8
8
|
import normalizeKey from '../../lib/normalize_key.js';
|
|
9
9
|
export class FlattenedSign {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
#payload;
|
|
11
|
+
#protectedHeader;
|
|
12
|
+
#unprotectedHeader;
|
|
13
13
|
constructor(payload) {
|
|
14
14
|
if (!(payload instanceof Uint8Array)) {
|
|
15
15
|
throw new TypeError('payload must be an instance of Uint8Array');
|
|
16
16
|
}
|
|
17
|
-
this
|
|
17
|
+
this.#payload = payload;
|
|
18
18
|
}
|
|
19
19
|
setProtectedHeader(protectedHeader) {
|
|
20
|
-
if (this
|
|
20
|
+
if (this.#protectedHeader) {
|
|
21
21
|
throw new TypeError('setProtectedHeader can only be called once');
|
|
22
22
|
}
|
|
23
|
-
this
|
|
23
|
+
this.#protectedHeader = protectedHeader;
|
|
24
24
|
return this;
|
|
25
25
|
}
|
|
26
26
|
setUnprotectedHeader(unprotectedHeader) {
|
|
27
|
-
if (this
|
|
27
|
+
if (this.#unprotectedHeader) {
|
|
28
28
|
throw new TypeError('setUnprotectedHeader can only be called once');
|
|
29
29
|
}
|
|
30
|
-
this
|
|
30
|
+
this.#unprotectedHeader = unprotectedHeader;
|
|
31
31
|
return this;
|
|
32
32
|
}
|
|
33
33
|
async sign(key, options) {
|
|
34
|
-
if (!this
|
|
34
|
+
if (!this.#protectedHeader && !this.#unprotectedHeader) {
|
|
35
35
|
throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()');
|
|
36
36
|
}
|
|
37
|
-
if (!isDisjoint(this
|
|
37
|
+
if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader)) {
|
|
38
38
|
throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');
|
|
39
39
|
}
|
|
40
40
|
const joseHeader = {
|
|
41
|
-
...this
|
|
42
|
-
...this
|
|
41
|
+
...this.#protectedHeader,
|
|
42
|
+
...this.#unprotectedHeader,
|
|
43
43
|
};
|
|
44
|
-
const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, this
|
|
44
|
+
const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, this.#protectedHeader, joseHeader);
|
|
45
45
|
let b64 = true;
|
|
46
46
|
if (extensions.has('b64')) {
|
|
47
|
-
b64 = this.
|
|
47
|
+
b64 = this.#protectedHeader.b64;
|
|
48
48
|
if (typeof b64 !== 'boolean') {
|
|
49
49
|
throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
|
|
50
50
|
}
|
|
@@ -54,13 +54,13 @@ export class FlattenedSign {
|
|
|
54
54
|
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
|
|
55
55
|
}
|
|
56
56
|
checkKeyType(alg, key, 'sign');
|
|
57
|
-
let payload = this
|
|
57
|
+
let payload = this.#payload;
|
|
58
58
|
if (b64) {
|
|
59
59
|
payload = encoder.encode(b64u(payload));
|
|
60
60
|
}
|
|
61
61
|
let protectedHeader;
|
|
62
|
-
if (this
|
|
63
|
-
protectedHeader = encoder.encode(b64u(JSON.stringify(this
|
|
62
|
+
if (this.#protectedHeader) {
|
|
63
|
+
protectedHeader = encoder.encode(b64u(JSON.stringify(this.#protectedHeader)));
|
|
64
64
|
}
|
|
65
65
|
else {
|
|
66
66
|
protectedHeader = encoder.encode('');
|
|
@@ -75,10 +75,10 @@ export class FlattenedSign {
|
|
|
75
75
|
if (b64) {
|
|
76
76
|
jws.payload = decoder.decode(payload);
|
|
77
77
|
}
|
|
78
|
-
if (this
|
|
79
|
-
jws.header = this
|
|
78
|
+
if (this.#unprotectedHeader) {
|
|
79
|
+
jws.header = this.#unprotectedHeader;
|
|
80
80
|
}
|
|
81
|
-
if (this
|
|
81
|
+
if (this.#protectedHeader) {
|
|
82
82
|
jws.protected = decoder.decode(protectedHeader);
|
|
83
83
|
}
|
|
84
84
|
return jws;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { FlattenedSign } from '../flattened/sign.js';
|
|
2
2
|
import { JWSInvalid } from '../../util/errors.js';
|
|
3
3
|
class IndividualSignature {
|
|
4
|
-
parent;
|
|
4
|
+
#parent;
|
|
5
5
|
protectedHeader;
|
|
6
6
|
unprotectedHeader;
|
|
7
7
|
options;
|
|
8
8
|
key;
|
|
9
9
|
constructor(sig, key, options) {
|
|
10
|
-
this
|
|
10
|
+
this.#parent = sig;
|
|
11
11
|
this.key = key;
|
|
12
12
|
this.options = options;
|
|
13
13
|
}
|
|
@@ -26,37 +26,37 @@ class IndividualSignature {
|
|
|
26
26
|
return this;
|
|
27
27
|
}
|
|
28
28
|
addSignature(...args) {
|
|
29
|
-
return this
|
|
29
|
+
return this.#parent.addSignature(...args);
|
|
30
30
|
}
|
|
31
31
|
sign(...args) {
|
|
32
|
-
return this
|
|
32
|
+
return this.#parent.sign(...args);
|
|
33
33
|
}
|
|
34
34
|
done() {
|
|
35
|
-
return this
|
|
35
|
+
return this.#parent;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
export class GeneralSign {
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
#payload;
|
|
40
|
+
#signatures = [];
|
|
41
41
|
constructor(payload) {
|
|
42
|
-
this
|
|
42
|
+
this.#payload = payload;
|
|
43
43
|
}
|
|
44
44
|
addSignature(key, options) {
|
|
45
45
|
const signature = new IndividualSignature(this, key, options);
|
|
46
|
-
this.
|
|
46
|
+
this.#signatures.push(signature);
|
|
47
47
|
return signature;
|
|
48
48
|
}
|
|
49
49
|
async sign() {
|
|
50
|
-
if (!this.
|
|
50
|
+
if (!this.#signatures.length) {
|
|
51
51
|
throw new JWSInvalid('at least one signature must be added');
|
|
52
52
|
}
|
|
53
53
|
const jws = {
|
|
54
54
|
signatures: [],
|
|
55
55
|
payload: '',
|
|
56
56
|
};
|
|
57
|
-
for (let i = 0; i < this.
|
|
58
|
-
const signature = this
|
|
59
|
-
const flattened = new FlattenedSign(this
|
|
57
|
+
for (let i = 0; i < this.#signatures.length; i++) {
|
|
58
|
+
const signature = this.#signatures[i];
|
|
59
|
+
const flattened = new FlattenedSign(this.#payload);
|
|
60
60
|
flattened.setProtectedHeader(signature.protectedHeader);
|
|
61
61
|
flattened.setUnprotectedHeader(signature.unprotectedHeader);
|
|
62
62
|
const { payload, ...rest } = await flattened.sign(signature.key, signature.options);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { compactDecrypt } from '../jwe/compact/decrypt.js';
|
|
2
|
-
import
|
|
2
|
+
import { validateClaimsSet } from '../lib/jwt_claims_set.js';
|
|
3
3
|
import { JWTClaimValidationFailed } from '../util/errors.js';
|
|
4
4
|
export async function jwtDecrypt(jwt, key, options) {
|
|
5
5
|
const decrypted = await compactDecrypt(jwt, key, options);
|
|
6
|
-
const payload =
|
|
6
|
+
const payload = validateClaimsSet(decrypted.protectedHeader, decrypted.plaintext, options);
|
|
7
7
|
const { protectedHeader } = decrypted;
|
|
8
8
|
if (protectedHeader.iss !== undefined && protectedHeader.iss !== payload.iss) {
|
|
9
9
|
throw new JWTClaimValidationFailed('replicated "iss" claim header parameter mismatch', payload, 'iss', 'mismatch');
|
|
@@ -1,74 +1,107 @@
|
|
|
1
1
|
import { CompactEncrypt } from '../jwe/compact/encrypt.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
import { JWTClaimsBuilder } from '../lib/jwt_claims_set.js';
|
|
3
|
+
export class EncryptJWT {
|
|
4
|
+
#cek;
|
|
5
|
+
#iv;
|
|
6
|
+
#keyManagementParameters;
|
|
7
|
+
#protectedHeader;
|
|
8
|
+
#replicateIssuerAsHeader;
|
|
9
|
+
#replicateSubjectAsHeader;
|
|
10
|
+
#replicateAudienceAsHeader;
|
|
11
|
+
#jwt;
|
|
12
|
+
constructor(payload = {}) {
|
|
13
|
+
this.#jwt = new JWTClaimsBuilder(payload);
|
|
14
|
+
}
|
|
15
|
+
setIssuer(issuer) {
|
|
16
|
+
this.#jwt.iss = issuer;
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
setSubject(subject) {
|
|
20
|
+
this.#jwt.sub = subject;
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
setAudience(audience) {
|
|
24
|
+
this.#jwt.aud = audience;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
setJti(jwtId) {
|
|
28
|
+
this.#jwt.jti = jwtId;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
setNotBefore(input) {
|
|
32
|
+
this.#jwt.nbf = input;
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
setExpirationTime(input) {
|
|
36
|
+
this.#jwt.exp = input;
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
setIssuedAt(input) {
|
|
40
|
+
this.#jwt.iat = input;
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
12
43
|
setProtectedHeader(protectedHeader) {
|
|
13
|
-
if (this
|
|
44
|
+
if (this.#protectedHeader) {
|
|
14
45
|
throw new TypeError('setProtectedHeader can only be called once');
|
|
15
46
|
}
|
|
16
|
-
this
|
|
47
|
+
this.#protectedHeader = protectedHeader;
|
|
17
48
|
return this;
|
|
18
49
|
}
|
|
19
50
|
setKeyManagementParameters(parameters) {
|
|
20
|
-
if (this
|
|
51
|
+
if (this.#keyManagementParameters) {
|
|
21
52
|
throw new TypeError('setKeyManagementParameters can only be called once');
|
|
22
53
|
}
|
|
23
|
-
this
|
|
54
|
+
this.#keyManagementParameters = parameters;
|
|
24
55
|
return this;
|
|
25
56
|
}
|
|
26
57
|
setContentEncryptionKey(cek) {
|
|
27
|
-
if (this
|
|
58
|
+
if (this.#cek) {
|
|
28
59
|
throw new TypeError('setContentEncryptionKey can only be called once');
|
|
29
60
|
}
|
|
30
|
-
this
|
|
61
|
+
this.#cek = cek;
|
|
31
62
|
return this;
|
|
32
63
|
}
|
|
33
64
|
setInitializationVector(iv) {
|
|
34
|
-
if (this
|
|
65
|
+
if (this.#iv) {
|
|
35
66
|
throw new TypeError('setInitializationVector can only be called once');
|
|
36
67
|
}
|
|
37
|
-
this
|
|
68
|
+
this.#iv = iv;
|
|
38
69
|
return this;
|
|
39
70
|
}
|
|
40
71
|
replicateIssuerAsHeader() {
|
|
41
|
-
this
|
|
72
|
+
this.#replicateIssuerAsHeader = true;
|
|
42
73
|
return this;
|
|
43
74
|
}
|
|
44
75
|
replicateSubjectAsHeader() {
|
|
45
|
-
this
|
|
76
|
+
this.#replicateSubjectAsHeader = true;
|
|
46
77
|
return this;
|
|
47
78
|
}
|
|
48
79
|
replicateAudienceAsHeader() {
|
|
49
|
-
this
|
|
80
|
+
this.#replicateAudienceAsHeader = true;
|
|
50
81
|
return this;
|
|
51
82
|
}
|
|
52
83
|
async encrypt(key, options) {
|
|
53
|
-
const enc = new CompactEncrypt(
|
|
54
|
-
if (this
|
|
55
|
-
this
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
84
|
+
const enc = new CompactEncrypt(this.#jwt.data());
|
|
85
|
+
if (this.#protectedHeader &&
|
|
86
|
+
(this.#replicateIssuerAsHeader ||
|
|
87
|
+
this.#replicateSubjectAsHeader ||
|
|
88
|
+
this.#replicateAudienceAsHeader)) {
|
|
89
|
+
this.#protectedHeader = {
|
|
90
|
+
...this.#protectedHeader,
|
|
91
|
+
iss: this.#replicateIssuerAsHeader ? this.#jwt.iss : undefined,
|
|
92
|
+
sub: this.#replicateSubjectAsHeader ? this.#jwt.sub : undefined,
|
|
93
|
+
aud: this.#replicateAudienceAsHeader ? this.#jwt.aud : undefined,
|
|
94
|
+
};
|
|
62
95
|
}
|
|
63
|
-
enc.setProtectedHeader(this
|
|
64
|
-
if (this
|
|
65
|
-
enc.setInitializationVector(this
|
|
96
|
+
enc.setProtectedHeader(this.#protectedHeader);
|
|
97
|
+
if (this.#iv) {
|
|
98
|
+
enc.setInitializationVector(this.#iv);
|
|
66
99
|
}
|
|
67
|
-
if (this
|
|
68
|
-
enc.setContentEncryptionKey(this
|
|
100
|
+
if (this.#cek) {
|
|
101
|
+
enc.setContentEncryptionKey(this.#cek);
|
|
69
102
|
}
|
|
70
|
-
if (this
|
|
71
|
-
enc.setKeyManagementParameters(this
|
|
103
|
+
if (this.#keyManagementParameters) {
|
|
104
|
+
enc.setKeyManagementParameters(this.#keyManagementParameters);
|
|
72
105
|
}
|
|
73
106
|
return enc.encrypt(key, options);
|
|
74
107
|
}
|
package/dist/webapi/jwt/sign.js
CHANGED
|
@@ -1,19 +1,50 @@
|
|
|
1
1
|
import { CompactSign } from '../jws/compact/sign.js';
|
|
2
2
|
import { JWTInvalid } from '../util/errors.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { JWTClaimsBuilder } from '../lib/jwt_claims_set.js';
|
|
4
|
+
export class SignJWT {
|
|
5
|
+
#protectedHeader;
|
|
6
|
+
#jwt;
|
|
7
|
+
constructor(payload = {}) {
|
|
8
|
+
this.#jwt = new JWTClaimsBuilder(payload);
|
|
9
|
+
}
|
|
10
|
+
setIssuer(issuer) {
|
|
11
|
+
this.#jwt.iss = issuer;
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
setSubject(subject) {
|
|
15
|
+
this.#jwt.sub = subject;
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
setAudience(audience) {
|
|
19
|
+
this.#jwt.aud = audience;
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
setJti(jwtId) {
|
|
23
|
+
this.#jwt.jti = jwtId;
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
setNotBefore(input) {
|
|
27
|
+
this.#jwt.nbf = input;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
setExpirationTime(input) {
|
|
31
|
+
this.#jwt.exp = input;
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
setIssuedAt(input) {
|
|
35
|
+
this.#jwt.iat = input;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
7
38
|
setProtectedHeader(protectedHeader) {
|
|
8
|
-
this
|
|
39
|
+
this.#protectedHeader = protectedHeader;
|
|
9
40
|
return this;
|
|
10
41
|
}
|
|
11
42
|
async sign(key, options) {
|
|
12
|
-
const sig = new CompactSign(
|
|
13
|
-
sig.setProtectedHeader(this
|
|
14
|
-
if (Array.isArray(this
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
43
|
+
const sig = new CompactSign(this.#jwt.data());
|
|
44
|
+
sig.setProtectedHeader(this.#protectedHeader);
|
|
45
|
+
if (Array.isArray(this.#protectedHeader?.crit) &&
|
|
46
|
+
this.#protectedHeader.crit.includes('b64') &&
|
|
47
|
+
this.#protectedHeader.b64 === false) {
|
|
17
48
|
throw new JWTInvalid('JWTs MUST NOT use unencoded payload');
|
|
18
49
|
}
|
|
19
50
|
return sig.sign(key, options);
|
|
@@ -1,14 +1,45 @@
|
|
|
1
1
|
import * as b64u from '../util/base64url.js';
|
|
2
2
|
import { decoder } from '../lib/buffer_utils.js';
|
|
3
3
|
import { JWTInvalid } from '../util/errors.js';
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { validateClaimsSet, JWTClaimsBuilder } from '../lib/jwt_claims_set.js';
|
|
5
|
+
export class UnsecuredJWT {
|
|
6
|
+
#jwt;
|
|
7
|
+
constructor(payload = {}) {
|
|
8
|
+
this.#jwt = new JWTClaimsBuilder(payload);
|
|
9
|
+
}
|
|
7
10
|
encode() {
|
|
8
11
|
const header = b64u.encode(JSON.stringify({ alg: 'none' }));
|
|
9
|
-
const payload = b64u.encode(
|
|
12
|
+
const payload = b64u.encode(this.#jwt.data());
|
|
10
13
|
return `${header}.${payload}.`;
|
|
11
14
|
}
|
|
15
|
+
setIssuer(issuer) {
|
|
16
|
+
this.#jwt.iss = issuer;
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
setSubject(subject) {
|
|
20
|
+
this.#jwt.sub = subject;
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
setAudience(audience) {
|
|
24
|
+
this.#jwt.aud = audience;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
setJti(jwtId) {
|
|
28
|
+
this.#jwt.jti = jwtId;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
setNotBefore(input) {
|
|
32
|
+
this.#jwt.nbf = input;
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
setExpirationTime(input) {
|
|
36
|
+
this.#jwt.exp = input;
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
setIssuedAt(input) {
|
|
40
|
+
this.#jwt.iat = input;
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
12
43
|
static decode(jwt, options) {
|
|
13
44
|
if (typeof jwt !== 'string') {
|
|
14
45
|
throw new JWTInvalid('Unsecured JWT must be a string');
|
|
@@ -26,7 +57,7 @@ export class UnsecuredJWT extends ProduceJWT {
|
|
|
26
57
|
catch {
|
|
27
58
|
throw new JWTInvalid('Invalid Unsecured JWT');
|
|
28
59
|
}
|
|
29
|
-
const payload =
|
|
60
|
+
const payload = validateClaimsSet(header, b64u.decode(encodedPayload), options);
|
|
30
61
|
return { payload, header };
|
|
31
62
|
}
|
|
32
63
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { compactVerify } from '../jws/compact/verify.js';
|
|
2
|
-
import
|
|
2
|
+
import { validateClaimsSet } from '../lib/jwt_claims_set.js';
|
|
3
3
|
import { JWTInvalid } from '../util/errors.js';
|
|
4
4
|
export async function jwtVerify(jwt, key, options) {
|
|
5
5
|
const verified = await compactVerify(jwt, key, options);
|
|
6
6
|
if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) {
|
|
7
7
|
throw new JWTInvalid('JWTs MUST NOT use unencoded payload');
|
|
8
8
|
}
|
|
9
|
-
const payload =
|
|
9
|
+
const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
|
|
10
10
|
const result = { payload, protectedHeader: verified.protectedHeader };
|
|
11
11
|
if (typeof key === 'function') {
|
|
12
12
|
return { ...result, key: verified.key };
|
|
@@ -3,6 +3,13 @@ import { decoder } from './buffer_utils.js';
|
|
|
3
3
|
import epoch from './epoch.js';
|
|
4
4
|
import secs from './secs.js';
|
|
5
5
|
import isObject from './is_object.js';
|
|
6
|
+
import { encoder } from './buffer_utils.js';
|
|
7
|
+
function validateInput(label, input) {
|
|
8
|
+
if (!Number.isFinite(input)) {
|
|
9
|
+
throw new TypeError(`Invalid ${label} input`);
|
|
10
|
+
}
|
|
11
|
+
return input;
|
|
12
|
+
}
|
|
6
13
|
const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, '');
|
|
7
14
|
const checkAudiencePresence = (audPayload, audOption) => {
|
|
8
15
|
if (typeof audPayload === 'string') {
|
|
@@ -13,7 +20,7 @@ const checkAudiencePresence = (audPayload, audOption) => {
|
|
|
13
20
|
}
|
|
14
21
|
return false;
|
|
15
22
|
};
|
|
16
|
-
export
|
|
23
|
+
export function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
|
|
17
24
|
let payload;
|
|
18
25
|
try {
|
|
19
26
|
payload = JSON.parse(decoder.decode(encodedPayload));
|
|
@@ -101,4 +108,73 @@ export default (protectedHeader, encodedPayload, options = {}) => {
|
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
110
|
return payload;
|
|
104
|
-
}
|
|
111
|
+
}
|
|
112
|
+
export class JWTClaimsBuilder {
|
|
113
|
+
#payload;
|
|
114
|
+
constructor(payload) {
|
|
115
|
+
if (!isObject(payload)) {
|
|
116
|
+
throw new TypeError('JWT Claims Set MUST be an object');
|
|
117
|
+
}
|
|
118
|
+
this.#payload = structuredClone(payload);
|
|
119
|
+
}
|
|
120
|
+
data() {
|
|
121
|
+
return encoder.encode(JSON.stringify(this.#payload));
|
|
122
|
+
}
|
|
123
|
+
get iss() {
|
|
124
|
+
return this.#payload.iss;
|
|
125
|
+
}
|
|
126
|
+
set iss(value) {
|
|
127
|
+
this.#payload.iss = value;
|
|
128
|
+
}
|
|
129
|
+
get sub() {
|
|
130
|
+
return this.#payload.sub;
|
|
131
|
+
}
|
|
132
|
+
set sub(value) {
|
|
133
|
+
this.#payload.sub = value;
|
|
134
|
+
}
|
|
135
|
+
get aud() {
|
|
136
|
+
return this.#payload.aud;
|
|
137
|
+
}
|
|
138
|
+
set aud(value) {
|
|
139
|
+
this.#payload.aud = value;
|
|
140
|
+
}
|
|
141
|
+
set jti(value) {
|
|
142
|
+
this.#payload.jti = value;
|
|
143
|
+
}
|
|
144
|
+
set nbf(value) {
|
|
145
|
+
if (typeof value === 'number') {
|
|
146
|
+
this.#payload.nbf = validateInput('setNotBefore', value);
|
|
147
|
+
}
|
|
148
|
+
else if (value instanceof Date) {
|
|
149
|
+
this.#payload.nbf = validateInput('setNotBefore', epoch(value));
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
this.#payload.nbf = epoch(new Date()) + secs(value);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
set exp(value) {
|
|
156
|
+
if (typeof value === 'number') {
|
|
157
|
+
this.#payload.exp = validateInput('setExpirationTime', value);
|
|
158
|
+
}
|
|
159
|
+
else if (value instanceof Date) {
|
|
160
|
+
this.#payload.exp = validateInput('setExpirationTime', epoch(value));
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
this.#payload.exp = epoch(new Date()) + secs(value);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
set iat(value) {
|
|
167
|
+
if (typeof value === 'undefined') {
|
|
168
|
+
this.#payload.iat = epoch(new Date());
|
|
169
|
+
}
|
|
170
|
+
else if (value instanceof Date) {
|
|
171
|
+
this.#payload.iat = validateInput('setIssuedAt', epoch(value));
|
|
172
|
+
}
|
|
173
|
+
else if (typeof value === 'string') {
|
|
174
|
+
this.#payload.iat = validateInput('setIssuedAt', epoch(new Date()) + secs(value));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.#payload.iat = validateInput('setIssuedAt', value);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
package/package.json
CHANGED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import type * as types from '../types.d.ts';
|
|
2
|
-
/** Generic class for JWT producing. */
|
|
3
|
-
export declare class ProduceJWT {
|
|
4
|
-
protected _payload: types.JWTPayload;
|
|
5
|
-
/** @param payload The JWT Claims Set object. Defaults to an empty object. */
|
|
6
|
-
constructor(payload?: types.JWTPayload);
|
|
7
|
-
/**
|
|
8
|
-
* Set the "iss" (Issuer) Claim.
|
|
9
|
-
*
|
|
10
|
-
* @param issuer "Issuer" Claim value to set on the JWT Claims Set.
|
|
11
|
-
*/
|
|
12
|
-
setIssuer(issuer: string): this;
|
|
13
|
-
/**
|
|
14
|
-
* Set the "sub" (Subject) Claim.
|
|
15
|
-
*
|
|
16
|
-
* @param subject "sub" (Subject) Claim value to set on the JWT Claims Set.
|
|
17
|
-
*/
|
|
18
|
-
setSubject(subject: string): this;
|
|
19
|
-
/**
|
|
20
|
-
* Set the "aud" (Audience) Claim.
|
|
21
|
-
*
|
|
22
|
-
* @param audience "aud" (Audience) Claim value to set on the JWT Claims Set.
|
|
23
|
-
*/
|
|
24
|
-
setAudience(audience: string | string[]): this;
|
|
25
|
-
/**
|
|
26
|
-
* Set the "jti" (JWT ID) Claim.
|
|
27
|
-
*
|
|
28
|
-
* @param jwtId "jti" (JWT ID) Claim value to set on the JWT Claims Set.
|
|
29
|
-
*/
|
|
30
|
-
setJti(jwtId: string): this;
|
|
31
|
-
/**
|
|
32
|
-
* Set the "nbf" (Not Before) Claim.
|
|
33
|
-
*
|
|
34
|
-
* - If a `number` is passed as an argument it is used as the claim directly.
|
|
35
|
-
* - If a `Date` instance is passed as an argument it is converted to unix timestamp and used as the
|
|
36
|
-
* claim.
|
|
37
|
-
* - If a `string` is passed as an argument it is resolved to a time span, and then added to the
|
|
38
|
-
* current unix timestamp and used as the claim.
|
|
39
|
-
*
|
|
40
|
-
* Format used for time span should be a number followed by a unit, such as "5 minutes" or "1
|
|
41
|
-
* day".
|
|
42
|
-
*
|
|
43
|
-
* Valid units are: "sec", "secs", "second", "seconds", "s", "minute", "minutes", "min", "mins",
|
|
44
|
-
* "m", "hour", "hours", "hr", "hrs", "h", "day", "days", "d", "week", "weeks", "w", "year",
|
|
45
|
-
* "years", "yr", "yrs", and "y". It is not possible to specify months. 365.25 days is used as an
|
|
46
|
-
* alias for a year.
|
|
47
|
-
*
|
|
48
|
-
* If the string is suffixed with "ago", or prefixed with a "-", the resulting time span gets
|
|
49
|
-
* subtracted from the current unix timestamp. A "from now" suffix can also be used for
|
|
50
|
-
* readability when adding to the current unix timestamp.
|
|
51
|
-
*
|
|
52
|
-
* @param input "nbf" (Not Before) Claim value to set on the JWT Claims Set.
|
|
53
|
-
*/
|
|
54
|
-
setNotBefore(input: number | string | Date): this;
|
|
55
|
-
/**
|
|
56
|
-
* Set the "exp" (Expiration Time) Claim.
|
|
57
|
-
*
|
|
58
|
-
* - If a `number` is passed as an argument it is used as the claim directly.
|
|
59
|
-
* - If a `Date` instance is passed as an argument it is converted to unix timestamp and used as the
|
|
60
|
-
* claim.
|
|
61
|
-
* - If a `string` is passed as an argument it is resolved to a time span, and then added to the
|
|
62
|
-
* current unix timestamp and used as the claim.
|
|
63
|
-
*
|
|
64
|
-
* Format used for time span should be a number followed by a unit, such as "5 minutes" or "1
|
|
65
|
-
* day".
|
|
66
|
-
*
|
|
67
|
-
* Valid units are: "sec", "secs", "second", "seconds", "s", "minute", "minutes", "min", "mins",
|
|
68
|
-
* "m", "hour", "hours", "hr", "hrs", "h", "day", "days", "d", "week", "weeks", "w", "year",
|
|
69
|
-
* "years", "yr", "yrs", and "y". It is not possible to specify months. 365.25 days is used as an
|
|
70
|
-
* alias for a year.
|
|
71
|
-
*
|
|
72
|
-
* If the string is suffixed with "ago", or prefixed with a "-", the resulting time span gets
|
|
73
|
-
* subtracted from the current unix timestamp. A "from now" suffix can also be used for
|
|
74
|
-
* readability when adding to the current unix timestamp.
|
|
75
|
-
*
|
|
76
|
-
* @param input "exp" (Expiration Time) Claim value to set on the JWT Claims Set.
|
|
77
|
-
*/
|
|
78
|
-
setExpirationTime(input: number | string | Date): this;
|
|
79
|
-
/**
|
|
80
|
-
* Set the "iat" (Issued At) Claim.
|
|
81
|
-
*
|
|
82
|
-
* - If no argument is used the current unix timestamp is used as the claim.
|
|
83
|
-
* - If a `number` is passed as an argument it is used as the claim directly.
|
|
84
|
-
* - If a `Date` instance is passed as an argument it is converted to unix timestamp and used as the
|
|
85
|
-
* claim.
|
|
86
|
-
* - If a `string` is passed as an argument it is resolved to a time span, and then added to the
|
|
87
|
-
* current unix timestamp and used as the claim.
|
|
88
|
-
*
|
|
89
|
-
* Format used for time span should be a number followed by a unit, such as "5 minutes" or "1
|
|
90
|
-
* day".
|
|
91
|
-
*
|
|
92
|
-
* Valid units are: "sec", "secs", "second", "seconds", "s", "minute", "minutes", "min", "mins",
|
|
93
|
-
* "m", "hour", "hours", "hr", "hrs", "h", "day", "days", "d", "week", "weeks", "w", "year",
|
|
94
|
-
* "years", "yr", "yrs", and "y". It is not possible to specify months. 365.25 days is used as an
|
|
95
|
-
* alias for a year.
|
|
96
|
-
*
|
|
97
|
-
* If the string is suffixed with "ago", or prefixed with a "-", the resulting time span gets
|
|
98
|
-
* subtracted from the current unix timestamp. A "from now" suffix can also be used for
|
|
99
|
-
* readability when adding to the current unix timestamp.
|
|
100
|
-
*
|
|
101
|
-
* @param input "iat" (Expiration Time) Claim value to set on the JWT Claims Set.
|
|
102
|
-
*/
|
|
103
|
-
setIssuedAt(input?: number | string | Date): this;
|
|
104
|
-
}
|