@sourceregistry/node-jwt 1.5.11 → 1.6.0
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 +19 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +753 -22
- package/dist/index.js.map +1 -1
- package/dist/jwt/index.d.ts +5 -3
- package/dist/jwt/promises.d.ts +28 -28
- package/dist/promises.cjs +2 -2
- package/dist/promises.cjs.map +1 -1
- package/dist/promises.js +30 -43
- package/dist/promises.js.map +1 -1
- package/package.json +10 -10
- package/dist/index-BJnjMyHr.js +0 -803
- package/dist/index-BJnjMyHr.js.map +0 -1
- package/dist/index-BzmHAEeR.cjs +0 -2
- package/dist/index-BzmHAEeR.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,23 +1,754 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import e, { createHash as t, createHmac as n, createPrivateKey as r, createPublicKey as i, createSecretKey as a, createSign as o, createVerify as s, sign as c, timingSafeEqual as l, verify as u } from "crypto";
|
|
2
|
+
//#region src/jwt/index.ts
|
|
3
|
+
var d = {
|
|
4
|
+
encode: (e) => Buffer.from(e).toString("base64url"),
|
|
5
|
+
decode: (e) => Buffer.from(e, "base64url").toString()
|
|
6
|
+
}, f = (e, t) => e.length === t.length && l(Buffer.from(e), Buffer.from(t)), p = /^[A-Za-z0-9_-]+$/;
|
|
7
|
+
function m(e) {
|
|
8
|
+
return typeof e == "object" && !!e && !Array.isArray(e);
|
|
9
|
+
}
|
|
10
|
+
function h(e) {
|
|
11
|
+
return typeof e == "number" && Number.isFinite(e);
|
|
12
|
+
}
|
|
13
|
+
function g(e) {
|
|
14
|
+
return Array.isArray(e) && e.every((e) => typeof e == "string");
|
|
15
|
+
}
|
|
16
|
+
function _(e) {
|
|
17
|
+
let t = [
|
|
18
|
+
{
|
|
19
|
+
claim: "iss",
|
|
20
|
+
valid: e.iss === void 0 || typeof e.iss == "string",
|
|
21
|
+
expected: "string"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
claim: "sub",
|
|
25
|
+
valid: e.sub === void 0 || typeof e.sub == "string",
|
|
26
|
+
expected: "string"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
claim: "jti",
|
|
30
|
+
valid: e.jti === void 0 || typeof e.jti == "string",
|
|
31
|
+
expected: "string"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
claim: "sid",
|
|
35
|
+
valid: e.sid === void 0 || typeof e.sid == "string",
|
|
36
|
+
expected: "string"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
claim: "iat",
|
|
40
|
+
valid: e.iat === void 0 || h(e.iat),
|
|
41
|
+
expected: "number"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
claim: "exp",
|
|
45
|
+
valid: e.exp === void 0 || h(e.exp),
|
|
46
|
+
expected: "number"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
claim: "nbf",
|
|
50
|
+
valid: e.nbf === void 0 || h(e.nbf),
|
|
51
|
+
expected: "number"
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
for (let e of t) if (!e.valid) return {
|
|
55
|
+
reason: `Invalid "${e.claim}" claim: expected ${e.expected}`,
|
|
56
|
+
code: "INVALID_CLAIM"
|
|
57
|
+
};
|
|
58
|
+
return e.aud !== void 0 && !(typeof e.aud == "string" || g(e.aud)) ? {
|
|
59
|
+
reason: "Invalid \"aud\" claim: expected string or string[]",
|
|
60
|
+
code: "INVALID_CLAIM"
|
|
61
|
+
} : null;
|
|
62
|
+
}
|
|
63
|
+
function v(e) {
|
|
64
|
+
if (e.signatureFormat !== void 0 && e.signatureFormat !== "der" && e.signatureFormat !== "jose") return {
|
|
65
|
+
reason: "Invalid signatureFormat option: expected \"der\" or \"jose\"",
|
|
66
|
+
code: "INVALID_OPTIONS"
|
|
67
|
+
};
|
|
68
|
+
if (e.clockSkew !== void 0 && (!h(e.clockSkew) || e.clockSkew < 0)) return {
|
|
69
|
+
reason: "Invalid clockSkew option: expected a non-negative finite number",
|
|
70
|
+
code: "INVALID_OPTIONS"
|
|
71
|
+
};
|
|
72
|
+
if (e.maxTokenAge !== void 0 && (!h(e.maxTokenAge) || e.maxTokenAge < 0)) return {
|
|
73
|
+
reason: "Invalid maxTokenAge option: expected a non-negative finite number",
|
|
74
|
+
code: "INVALID_OPTIONS"
|
|
75
|
+
};
|
|
76
|
+
if (e.ignoreExpiration !== void 0 && typeof e.ignoreExpiration != "boolean") return {
|
|
77
|
+
reason: "Invalid ignoreExpiration option: expected boolean",
|
|
78
|
+
code: "INVALID_OPTIONS"
|
|
79
|
+
};
|
|
80
|
+
if (e.issuer !== void 0 && typeof e.issuer != "string") return {
|
|
81
|
+
reason: "Invalid issuer option: expected string",
|
|
82
|
+
code: "INVALID_OPTIONS"
|
|
83
|
+
};
|
|
84
|
+
if (e.subject !== void 0 && typeof e.subject != "string") return {
|
|
85
|
+
reason: "Invalid subject option: expected string",
|
|
86
|
+
code: "INVALID_OPTIONS"
|
|
87
|
+
};
|
|
88
|
+
if (e.jwtId !== void 0 && typeof e.jwtId != "string") return {
|
|
89
|
+
reason: "Invalid jwtId option: expected string",
|
|
90
|
+
code: "INVALID_OPTIONS"
|
|
91
|
+
};
|
|
92
|
+
if (e.audience !== void 0 && !(typeof e.audience == "string" || g(e.audience))) return {
|
|
93
|
+
reason: "Invalid audience option: expected string or string[]",
|
|
94
|
+
code: "INVALID_OPTIONS"
|
|
95
|
+
};
|
|
96
|
+
if (e.algorithms !== void 0) {
|
|
97
|
+
if (!Array.isArray(e.algorithms) || e.algorithms.length === 0) return {
|
|
98
|
+
reason: "Invalid algorithms option: expected a non-empty array",
|
|
99
|
+
code: "INVALID_OPTIONS"
|
|
100
|
+
};
|
|
101
|
+
let t = e.algorithms.find((e) => !(e in D));
|
|
102
|
+
if (t) return {
|
|
103
|
+
reason: `Invalid algorithms option: unsupported algorithm "${t}"`,
|
|
104
|
+
code: "INVALID_OPTIONS"
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (e.tokenTypes !== void 0) {
|
|
108
|
+
if (!Array.isArray(e.tokenTypes) || e.tokenTypes.length === 0 || !g(e.tokenTypes)) return {
|
|
109
|
+
reason: "Invalid tokenTypes option: expected a non-empty string[]",
|
|
110
|
+
code: "INVALID_OPTIONS"
|
|
111
|
+
};
|
|
112
|
+
if (e.tokenTypes.some((e) => e.length === 0)) return {
|
|
113
|
+
reason: "Invalid tokenTypes option: token types must not be empty",
|
|
114
|
+
code: "INVALID_OPTIONS"
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
function y(e) {
|
|
120
|
+
return e.crit === void 0 ? null : !g(e.crit) || e.crit.length === 0 ? {
|
|
121
|
+
reason: "Invalid \"crit\" header: expected non-empty string[]",
|
|
122
|
+
code: "INVALID_HEADER"
|
|
123
|
+
} : {
|
|
124
|
+
reason: `Unsupported critical header parameters: ${e.crit.join(", ")}`,
|
|
125
|
+
code: "UNSUPPORTED_CRITICAL_HEADER"
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function b(e) {
|
|
129
|
+
switch (e) {
|
|
130
|
+
case "ES256":
|
|
131
|
+
case "ES256K": return 64;
|
|
132
|
+
case "ES384": return 96;
|
|
133
|
+
case "ES512": return 132;
|
|
134
|
+
/* c8 ignore next 2 */
|
|
135
|
+
default: throw Error(`Unsupported ECDSA alg for JOSE conversion: ${e}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function x(e, t) {
|
|
139
|
+
let n = 0;
|
|
140
|
+
if (e[n++] !== 48) throw Error("Invalid DER ECDSA signature");
|
|
141
|
+
let r = e[n++];
|
|
142
|
+
if (r & 128) {
|
|
143
|
+
let t = r & 127;
|
|
144
|
+
r = 0;
|
|
145
|
+
for (let i = 0; i < t; i++) r = r << 8 | e[n++];
|
|
146
|
+
}
|
|
147
|
+
if (e[n++] !== 2) throw Error("Invalid DER ECDSA signature (r)");
|
|
148
|
+
let i = e[n++], a = e.subarray(n, n + i);
|
|
149
|
+
if (n += i, e[n++] !== 2) throw Error("Invalid DER ECDSA signature (s)");
|
|
150
|
+
let o = e[n++], s = e.subarray(n, n + o);
|
|
151
|
+
for (; a.length > t / 2 && a[0] === 0;) a = a.subarray(1);
|
|
152
|
+
for (; s.length > t / 2 && s[0] === 0;) s = s.subarray(1);
|
|
153
|
+
let c = Buffer.concat([Buffer.alloc(t / 2 - a.length, 0), a]), l = Buffer.concat([Buffer.alloc(t / 2 - s.length, 0), s]);
|
|
154
|
+
return Buffer.concat([c, l]);
|
|
155
|
+
}
|
|
156
|
+
function S(e) {
|
|
157
|
+
let t = e.length / 2, n = e.subarray(0, t), r = e.subarray(t);
|
|
158
|
+
for (; n.length > 1 && n[0] === 0 && !(n[1] & 128);) n = n.subarray(1);
|
|
159
|
+
for (; r.length > 1 && r[0] === 0 && !(r[1] & 128);) r = r.subarray(1);
|
|
160
|
+
n[0] & 128 && (n = Buffer.concat([Buffer.from([0]), n])), r[0] & 128 && (r = Buffer.concat([Buffer.from([0]), r]));
|
|
161
|
+
let i = Buffer.concat([Buffer.from([2, n.length]), n]), a = Buffer.concat([Buffer.from([2, r.length]), r]), o = i.length + a.length, s;
|
|
162
|
+
if (o < 128) s = Buffer.from([o]);
|
|
163
|
+
else {
|
|
164
|
+
let e = [], t = o;
|
|
165
|
+
for (; t > 0;) e.unshift(t & 255), t >>= 8;
|
|
166
|
+
s = Buffer.from([128 | e.length, ...e]);
|
|
167
|
+
}
|
|
168
|
+
return Buffer.concat([
|
|
169
|
+
Buffer.from([48]),
|
|
170
|
+
s,
|
|
171
|
+
i,
|
|
172
|
+
a
|
|
173
|
+
]);
|
|
174
|
+
}
|
|
175
|
+
function C(e) {
|
|
176
|
+
return e === "ES256" || e === "ES384" || e === "ES512" || e === "ES256K";
|
|
177
|
+
}
|
|
178
|
+
var w = (e) => ({
|
|
179
|
+
sign: (t, r) => n(e, r).update(t).digest("base64url"),
|
|
180
|
+
verify: (t, r, i) => f(n(e, r).update(t).digest("base64url"), i)
|
|
181
|
+
}), T = (e) => ({
|
|
182
|
+
sign: (t, n) => o(e).update(t).end().sign(n).toString("base64url"),
|
|
183
|
+
verify: (t, n, r) => {
|
|
184
|
+
try {
|
|
185
|
+
return s(e).update(t).end().verify(n, Buffer.from(r, "base64url"));
|
|
186
|
+
} catch {
|
|
187
|
+
return !1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}), E = (t, n) => ({
|
|
191
|
+
sign: (r, i) => o(t).update(r).end().sign({
|
|
192
|
+
key: i,
|
|
193
|
+
padding: e.constants.RSA_PKCS1_PSS_PADDING,
|
|
194
|
+
saltLength: n
|
|
195
|
+
}).toString("base64url"),
|
|
196
|
+
verify: (r, i, a) => {
|
|
197
|
+
try {
|
|
198
|
+
return s(t).update(r).end().verify({
|
|
199
|
+
key: i,
|
|
200
|
+
padding: e.constants.RSA_PKCS1_PSS_PADDING,
|
|
201
|
+
saltLength: n
|
|
202
|
+
}, Buffer.from(a, "base64url"));
|
|
203
|
+
} catch {
|
|
204
|
+
return !1;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}), D = {
|
|
208
|
+
HS256: w("sha256"),
|
|
209
|
+
HS384: w("sha384"),
|
|
210
|
+
HS512: w("sha512"),
|
|
211
|
+
RS256: T("RSA-SHA256"),
|
|
212
|
+
RS384: T("RSA-SHA384"),
|
|
213
|
+
RS512: T("RSA-SHA512"),
|
|
214
|
+
ES256: T("SHA256"),
|
|
215
|
+
ES384: T("SHA384"),
|
|
216
|
+
ES512: T("SHA512"),
|
|
217
|
+
ES256K: T("SHA256"),
|
|
218
|
+
PS256: E("RSA-SHA256", 32),
|
|
219
|
+
PS384: E("RSA-SHA384", 48),
|
|
220
|
+
PS512: E("RSA-SHA512", 64),
|
|
221
|
+
EdDSA: {
|
|
222
|
+
sign: (e, t) => c(null, typeof e == "string" ? Buffer.from(e, "utf8") : e, t).toString("base64url"),
|
|
223
|
+
verify: (e, t, n) => {
|
|
224
|
+
try {
|
|
225
|
+
return u(null, typeof e == "string" ? Buffer.from(e, "utf8") : e, t, Buffer.from(n, "base64url"));
|
|
226
|
+
} catch {
|
|
227
|
+
return !1;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}, O = Object.keys(D);
|
|
232
|
+
function k(e) {
|
|
233
|
+
if (e.type === "secret") return "HS256";
|
|
234
|
+
if (e.type !== "private") throw Error("Only private or symmetric keys can be used to sign JWTs");
|
|
235
|
+
let t = e.asymmetricKeyType, n = e.asymmetricKeyDetails;
|
|
236
|
+
switch (t) {
|
|
237
|
+
case "rsa": return "RS256";
|
|
238
|
+
case "rsa-pss": {
|
|
239
|
+
let e = (n == null ? void 0 : n.hashAlgorithm) ?? "sha256";
|
|
240
|
+
switch (e) {
|
|
241
|
+
case "sha256": return "PS256";
|
|
242
|
+
case "sha384": return "PS384";
|
|
243
|
+
case "sha512": return "PS512";
|
|
244
|
+
default: throw Error(`Unsupported RSA-PSS hash algorithm: ${e}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
case "ec": {
|
|
248
|
+
let e = n == null ? void 0 : n.namedCurve;
|
|
249
|
+
switch (e) {
|
|
250
|
+
case "P-256":
|
|
251
|
+
case "prime256v1": return "ES256";
|
|
252
|
+
case "P-384":
|
|
253
|
+
case "secp384r1": return "ES384";
|
|
254
|
+
case "P-521":
|
|
255
|
+
case "secp521r1": return "ES512";
|
|
256
|
+
case "secp256k1": return "ES256K";
|
|
257
|
+
default: throw Error(`Unsupported EC curve: ${e}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
case "ed25519": return "EdDSA";
|
|
261
|
+
default: throw Error(`Unsupported asymmetric key type: ${t}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function A(e, t) {
|
|
265
|
+
if (typeof e == "object" && "type" in e) return e;
|
|
266
|
+
try {
|
|
267
|
+
return t === "sign" ? r(e) : i(e);
|
|
268
|
+
} catch {
|
|
269
|
+
if (t === "sign") {
|
|
270
|
+
try {
|
|
271
|
+
i(e);
|
|
272
|
+
} catch {
|
|
273
|
+
if (typeof e == "string") return a(Buffer.from(e, "utf8"));
|
|
274
|
+
if (Buffer.isBuffer(e)) return a(e);
|
|
275
|
+
throw Error("Unsupported key type");
|
|
276
|
+
}
|
|
277
|
+
throw Error("A public key cannot be used to sign JWTs");
|
|
278
|
+
}
|
|
279
|
+
if (typeof e == "string") return a(Buffer.from(e, "utf8"));
|
|
280
|
+
if (Buffer.isBuffer(e)) return a(e);
|
|
281
|
+
throw Error("Unsupported key type");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function j(e, t, n) {
|
|
285
|
+
if (t.startsWith("HS")) {
|
|
286
|
+
if (e.type !== "secret") throw Error(`${t} requires a symmetric secret key`);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (n === "sign" && e.type !== "private") throw Error(`${t} requires a private key for signing`);
|
|
290
|
+
if (n === "verify" && e.type !== "public" && e.type !== "private") throw Error(`${t} requires a public or private key for verification`);
|
|
291
|
+
let r = e.asymmetricKeyType;
|
|
292
|
+
if (t.startsWith("RS") && r !== "rsa") throw Error(`${t} requires an RSA key`);
|
|
293
|
+
if (t.startsWith("PS") && r !== "rsa" && r !== "rsa-pss") throw Error(`${t} requires an RSA or RSA-PSS key`);
|
|
294
|
+
if (t === "EdDSA" && r !== "ed25519") throw Error("EdDSA requires an Ed25519 key");
|
|
295
|
+
if (C(t)) {
|
|
296
|
+
var i;
|
|
297
|
+
let n = (i = e.asymmetricKeyDetails) == null ? void 0 : i.namedCurve, a = [];
|
|
298
|
+
switch (t) {
|
|
299
|
+
case "ES256":
|
|
300
|
+
a = ["P-256", "prime256v1"];
|
|
301
|
+
break;
|
|
302
|
+
case "ES384":
|
|
303
|
+
a = ["P-384", "secp384r1"];
|
|
304
|
+
break;
|
|
305
|
+
case "ES512":
|
|
306
|
+
a = ["P-521", "secp521r1"];
|
|
307
|
+
break;
|
|
308
|
+
case "ES256K": a = ["secp256k1"];
|
|
309
|
+
}
|
|
310
|
+
if (r !== "ec" || !a.includes(n ?? "")) throw Error(`${t} requires its matching EC curve`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
var M = (e) => {
|
|
314
|
+
let t = e.split(".");
|
|
315
|
+
if (t.length !== 3) throw Error("Invalid JWT: must contain exactly 3 parts separated by \".\"");
|
|
316
|
+
let [n, r, i] = t;
|
|
317
|
+
if (!n || !r || !i) throw Error("Invalid JWT: empty part detected");
|
|
318
|
+
if (!p.test(n) || !p.test(r) || !p.test(i)) throw Error("Invalid JWT: non-base64url characters detected");
|
|
319
|
+
try {
|
|
320
|
+
let e = JSON.parse(d.decode(n)), t = JSON.parse(d.decode(r));
|
|
321
|
+
if (!m(e) || !m(t)) throw Error("header and payload must be JSON objects");
|
|
322
|
+
let a = e, o = t;
|
|
323
|
+
if (typeof a.alg != "string" || a.alg.length === 0) throw Error("header.alg must be a non-empty string");
|
|
324
|
+
if (a.typ !== void 0 && typeof a.typ != "string") throw Error("header.typ must be a string");
|
|
325
|
+
if (a.kid !== void 0 && typeof a.kid != "string") throw Error("header.kid must be a string");
|
|
326
|
+
if (a.crit !== void 0 && (!g(a.crit) || a.crit.length === 0)) throw Error("header.crit must be a non-empty string[]");
|
|
327
|
+
return {
|
|
328
|
+
header: a,
|
|
329
|
+
payload: o,
|
|
330
|
+
signature: i
|
|
331
|
+
};
|
|
332
|
+
} catch (e) {
|
|
333
|
+
throw Error(`Invalid JWT: malformed header or payload (${e.message})`);
|
|
334
|
+
}
|
|
335
|
+
}, N = (e, t, n = {}) => {
|
|
336
|
+
let r = A(t, "sign"), i = n.alg ?? k(r), a = n.signatureFormat ?? (C(i) ? "jose" : "der"), o = n.typ ?? "JWT";
|
|
337
|
+
if (!(i in D)) throw Error(`Unsupported algorithm: ${i}`);
|
|
338
|
+
j(r, i, "sign");
|
|
339
|
+
let s = {
|
|
340
|
+
alg: i,
|
|
341
|
+
typ: o
|
|
342
|
+
};
|
|
343
|
+
n.kid && (s.kid = n.kid);
|
|
344
|
+
let c = d.encode(JSON.stringify(s)), l = d.encode(JSON.stringify(e)), u = `${c}.${l}`, f = D[i].sign(u, r);
|
|
345
|
+
return a === "jose" && C(i) && (f = x(Buffer.from(f, "base64url"), b(i)).toString("base64url")), `${c}.${l}.${f}`;
|
|
346
|
+
}, P = (e, t, n = {}) => {
|
|
347
|
+
let r = v(n);
|
|
348
|
+
if (r) return {
|
|
349
|
+
valid: !1,
|
|
350
|
+
error: r
|
|
351
|
+
};
|
|
352
|
+
let i;
|
|
353
|
+
try {
|
|
354
|
+
i = M(e);
|
|
355
|
+
} catch (e) {
|
|
356
|
+
return {
|
|
357
|
+
valid: !1,
|
|
358
|
+
error: {
|
|
359
|
+
reason: e.message,
|
|
360
|
+
code: "INVALID_TOKEN"
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
let { header: a, payload: o, signature: s } = i, c = y(a);
|
|
365
|
+
if (c) return {
|
|
366
|
+
valid: !1,
|
|
367
|
+
error: c
|
|
368
|
+
};
|
|
369
|
+
let l = _(o);
|
|
370
|
+
if (l) return {
|
|
371
|
+
valid: !1,
|
|
372
|
+
error: l
|
|
373
|
+
};
|
|
374
|
+
let u = a.alg;
|
|
375
|
+
if (!(u in D)) return {
|
|
376
|
+
valid: !1,
|
|
377
|
+
error: {
|
|
378
|
+
reason: `Unsupported or unknown algorithm: ${a.alg}`,
|
|
379
|
+
code: "INVALID_ALGORITHM"
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
if (n.algorithms && n.algorithms.length > 0 && !n.algorithms.includes(u)) return {
|
|
383
|
+
valid: !1,
|
|
384
|
+
error: {
|
|
385
|
+
reason: `Algorithm "${u}" is not in the allowed algorithms list`,
|
|
386
|
+
code: "ALGORITHM_NOT_ALLOWED"
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
let d = n.tokenTypes ?? ["JWT"];
|
|
390
|
+
if (a.typ !== void 0 && !d.includes(a.typ)) return {
|
|
391
|
+
valid: !1,
|
|
392
|
+
error: {
|
|
393
|
+
reason: `Invalid token type: expected one of ${d.map((e) => `'${e}'`).join(", ")}, got '${a.typ}'`,
|
|
394
|
+
code: "INVALID_TYPE"
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
let [f, p] = e.split("."), m = `${f}.${p}`, h;
|
|
398
|
+
try {
|
|
399
|
+
h = A(t, "verify"), j(h, u, "verify");
|
|
400
|
+
} catch (e) {
|
|
401
|
+
return {
|
|
402
|
+
valid: !1,
|
|
403
|
+
error: {
|
|
404
|
+
reason: e.message,
|
|
405
|
+
code: "KEY_ALGORITHM_MISMATCH"
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
if (C(u)) {
|
|
410
|
+
let e = n.signatureFormat, t;
|
|
411
|
+
if (e === "jose") try {
|
|
412
|
+
let e = S(Buffer.from(s, "base64url")).toString("base64url");
|
|
413
|
+
t = D[u].verify(m, h, e);
|
|
414
|
+
} catch {
|
|
415
|
+
t = !1;
|
|
416
|
+
}
|
|
417
|
+
else if (e === "der") t = D[u].verify(m, h, s);
|
|
418
|
+
else if (t = D[u].verify(m, h, s), !t) try {
|
|
419
|
+
let e = Buffer.from(s, "base64url");
|
|
420
|
+
if (e.length === b(u)) {
|
|
421
|
+
let n = S(e).toString("base64url");
|
|
422
|
+
t = D[u].verify(m, h, n);
|
|
423
|
+
}
|
|
424
|
+
} catch {}
|
|
425
|
+
if (!t) return {
|
|
426
|
+
valid: !1,
|
|
427
|
+
error: {
|
|
428
|
+
reason: "Signature verification failed",
|
|
429
|
+
code: "INVALID_SIGNATURE"
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
} else {
|
|
433
|
+
let e = !1;
|
|
434
|
+
try {
|
|
435
|
+
e = D[u].verify(m, h, s);
|
|
436
|
+
} catch {
|
|
437
|
+
e = !1;
|
|
438
|
+
}
|
|
439
|
+
if (!e) return {
|
|
440
|
+
valid: !1,
|
|
441
|
+
error: {
|
|
442
|
+
reason: "Signature verification failed",
|
|
443
|
+
code: "INVALID_SIGNATURE"
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
let g = Math.floor(Date.now() / 1e3), x = n.clockSkew ?? 0;
|
|
448
|
+
if (!n.ignoreExpiration && o.exp !== void 0 && g > o.exp + x) return {
|
|
449
|
+
valid: !1,
|
|
450
|
+
error: {
|
|
451
|
+
reason: "Token expired",
|
|
452
|
+
code: "TOKEN_EXPIRED"
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
if (o.nbf !== void 0 && g + x < o.nbf) return {
|
|
456
|
+
valid: !1,
|
|
457
|
+
error: {
|
|
458
|
+
reason: "Token not yet valid",
|
|
459
|
+
code: "TOKEN_NOT_ACTIVE"
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
if (o.iat !== void 0 && g + x < o.iat) return {
|
|
463
|
+
valid: !1,
|
|
464
|
+
error: {
|
|
465
|
+
reason: "Token issued in the future",
|
|
466
|
+
code: "TOKEN_FUTURE_ISSUED"
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
if (n.maxTokenAge !== void 0 && o.iat === void 0) return {
|
|
470
|
+
valid: !1,
|
|
471
|
+
error: {
|
|
472
|
+
reason: "Token missing required issued-at claim (\"iat\")",
|
|
473
|
+
code: "MISSING_IAT"
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
if (n.maxTokenAge !== void 0 && o.iat !== void 0) {
|
|
477
|
+
let e = g - o.iat;
|
|
478
|
+
if (e > n.maxTokenAge) return {
|
|
479
|
+
valid: !1,
|
|
480
|
+
error: {
|
|
481
|
+
reason: `Token age (${e}s) exceeds maximum allowed age (${n.maxTokenAge}s)`,
|
|
482
|
+
code: "TOKEN_TOO_OLD"
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
if (n.issuer !== void 0) {
|
|
487
|
+
if (o.iss === void 0) return {
|
|
488
|
+
valid: !1,
|
|
489
|
+
error: {
|
|
490
|
+
reason: "Token missing required issuer claim (\"iss\")",
|
|
491
|
+
code: "MISSING_ISSUER"
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
if (n.issuer !== o.iss) return {
|
|
495
|
+
valid: !1,
|
|
496
|
+
error: {
|
|
497
|
+
reason: `Invalid token issuer: expected "${n.issuer}", got "${o.iss}"`,
|
|
498
|
+
code: "INVALID_ISSUER"
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
if (n.subject !== void 0) {
|
|
503
|
+
if (o.sub === void 0) return {
|
|
504
|
+
valid: !1,
|
|
505
|
+
error: {
|
|
506
|
+
reason: "Token missing required subject claim (\"sub\")",
|
|
507
|
+
code: "MISSING_SUBJECT"
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
if (n.subject !== o.sub) return {
|
|
511
|
+
valid: !1,
|
|
512
|
+
error: {
|
|
513
|
+
reason: `Invalid token subject: expected "${n.subject}", got "${o.sub}"`,
|
|
514
|
+
code: "INVALID_SUBJECT"
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
if (n.audience !== void 0) {
|
|
519
|
+
let e = o.aud;
|
|
520
|
+
if (e === void 0) return {
|
|
521
|
+
valid: !1,
|
|
522
|
+
error: {
|
|
523
|
+
reason: "Token missing required audience claim (\"aud\")",
|
|
524
|
+
code: "MISSING_AUDIENCE"
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
let t = Array.isArray(n.audience) ? n.audience : [n.audience], r = Array.isArray(e) ? e : [e];
|
|
528
|
+
if (!t.some((e) => r.includes(e))) return {
|
|
529
|
+
valid: !1,
|
|
530
|
+
error: {
|
|
531
|
+
reason: "Audience claim mismatch",
|
|
532
|
+
code: "INVALID_AUDIENCE"
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
if (n.jwtId !== void 0) {
|
|
537
|
+
if (o.jti === void 0) return {
|
|
538
|
+
valid: !1,
|
|
539
|
+
error: {
|
|
540
|
+
reason: "Token missing required JWT ID claim (\"jti\")",
|
|
541
|
+
code: "MISSING_JTI"
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
if (n.jwtId !== o.jti) return {
|
|
545
|
+
valid: !1,
|
|
546
|
+
error: {
|
|
547
|
+
reason: `Invalid JWT ID: expected "${n.jwtId}", got "${o.jti}"`,
|
|
548
|
+
code: "INVALID_JTI"
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
return {
|
|
553
|
+
valid: !0,
|
|
554
|
+
header: a,
|
|
555
|
+
payload: o,
|
|
556
|
+
signature: s
|
|
557
|
+
};
|
|
558
|
+
}, F = {
|
|
559
|
+
sign: N,
|
|
560
|
+
verify: P,
|
|
561
|
+
decode: M,
|
|
562
|
+
algorithms: D
|
|
22
563
|
};
|
|
23
|
-
//#
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region src/jwks/index.ts
|
|
566
|
+
function I(e) {
|
|
567
|
+
if (!e || typeof e != "object") throw Error("Invalid KeyObject");
|
|
568
|
+
return e.export({ format: "jwk" });
|
|
569
|
+
}
|
|
570
|
+
function L(e) {
|
|
571
|
+
if (!e || typeof e != "object") throw Error("Invalid JWK");
|
|
572
|
+
switch (e.kty) {
|
|
573
|
+
case "oct":
|
|
574
|
+
if (!("k" in e) || typeof e.k != "string") throw Error("Invalid oct JWK: missing \"k\"");
|
|
575
|
+
return a(Buffer.from(e.k, "base64url"));
|
|
576
|
+
case "RSA":
|
|
577
|
+
case "EC":
|
|
578
|
+
case "OKP": return "d" in e && typeof e.d == "string" ? r({
|
|
579
|
+
format: "jwk",
|
|
580
|
+
key: e
|
|
581
|
+
}) : i({
|
|
582
|
+
format: "jwk",
|
|
583
|
+
key: e
|
|
584
|
+
});
|
|
585
|
+
default: throw Error(`Unsupported JWK key type: ${e.kty}`);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
function R(e) {
|
|
589
|
+
if (!e || typeof e != "object") throw Error("Invalid KeyObject");
|
|
590
|
+
let t = (e.type === "private" ? i(e) : e).export({ format: "jwk" });
|
|
591
|
+
return delete t.d, delete t.p, delete t.q, delete t.dp, delete t.dq, delete t.qi, t;
|
|
592
|
+
}
|
|
593
|
+
function z(e, n = "sha256") {
|
|
594
|
+
if (!e || typeof e != "object") throw Error("Invalid JWK");
|
|
595
|
+
let r;
|
|
596
|
+
switch (e.kty) {
|
|
597
|
+
case "RSA":
|
|
598
|
+
r = {
|
|
599
|
+
e: e.e,
|
|
600
|
+
kty: e.kty,
|
|
601
|
+
n: e.n
|
|
602
|
+
};
|
|
603
|
+
break;
|
|
604
|
+
case "EC":
|
|
605
|
+
r = {
|
|
606
|
+
crv: e.crv,
|
|
607
|
+
kty: e.kty,
|
|
608
|
+
x: e.x,
|
|
609
|
+
y: e.y
|
|
610
|
+
};
|
|
611
|
+
break;
|
|
612
|
+
case "OKP":
|
|
613
|
+
r = {
|
|
614
|
+
crv: e.crv,
|
|
615
|
+
kty: e.kty,
|
|
616
|
+
x: e.x
|
|
617
|
+
};
|
|
618
|
+
break;
|
|
619
|
+
case "oct":
|
|
620
|
+
r = {
|
|
621
|
+
k: e.k,
|
|
622
|
+
kty: e.kty
|
|
623
|
+
};
|
|
624
|
+
break;
|
|
625
|
+
default: throw Error(`Unsupported JWK key type: ${e.kty}`);
|
|
626
|
+
}
|
|
627
|
+
let i = JSON.stringify(Object.keys(r).sort().reduce((e, t) => (e[t] = r[t], e), {}));
|
|
628
|
+
return t(n).update(i).digest("base64url");
|
|
629
|
+
}
|
|
630
|
+
function B(e) {
|
|
631
|
+
var n;
|
|
632
|
+
if ((n = e.x5c) != null && n.length) return t("sha1").update(Buffer.from(e.x5c[0], "base64")).digest("base64url");
|
|
633
|
+
}
|
|
634
|
+
var V = {
|
|
635
|
+
export: I,
|
|
636
|
+
import: L,
|
|
637
|
+
toPublic: R,
|
|
638
|
+
thumbprint: z
|
|
639
|
+
};
|
|
640
|
+
function H(e, t) {
|
|
641
|
+
if (!e || !Array.isArray(e.keys)) throw Error("Invalid JWKS");
|
|
642
|
+
let n;
|
|
643
|
+
if (t && (n = e.keys.find((e) => e.kid === t)), !n && e.keys.length === 1 && (n = e.keys[0]), !n) throw Error("Key not found in JWKS");
|
|
644
|
+
return L(n);
|
|
645
|
+
}
|
|
646
|
+
function U(e) {
|
|
647
|
+
return { keys: W(...e.keys) };
|
|
648
|
+
}
|
|
649
|
+
function W(...e) {
|
|
650
|
+
return e.map((e) => {
|
|
651
|
+
let t = {
|
|
652
|
+
...e,
|
|
653
|
+
kid: e.kid ?? z(e),
|
|
654
|
+
x5t: e.x5t ?? B(e)
|
|
655
|
+
};
|
|
656
|
+
return Object.defineProperty(t, "toKeyObject", {
|
|
657
|
+
enumerable: !1,
|
|
658
|
+
configurable: !1,
|
|
659
|
+
writable: !1,
|
|
660
|
+
value: () => L(t)
|
|
661
|
+
}), t;
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
var G = async (e, t = {}) => {
|
|
665
|
+
let n = typeof e == "string" ? e : e.toString(), r = t.fetch ?? globalThis.fetch, i = Math.max(0, t.ttl ?? 3e5), a = Math.max(0, t.timeoutMs ?? 5e3), o = "/.well-known/jwks.json";
|
|
666
|
+
if (!r) throw Error("No fetch implementation available");
|
|
667
|
+
let s = (() => {
|
|
668
|
+
if (t.endpointOverride) {
|
|
669
|
+
let e = t.endpointOverride;
|
|
670
|
+
try {
|
|
671
|
+
return new URL(e, n).toString();
|
|
672
|
+
} catch {
|
|
673
|
+
return e;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
return t.overrideEndpointCheck || n.endsWith(o) ? n : `${n.replace(/\/+$/, "")}${o}`;
|
|
677
|
+
})(), c = (() => {
|
|
678
|
+
if (t.cache) return t.cache;
|
|
679
|
+
let e;
|
|
680
|
+
return {
|
|
681
|
+
get: () => e,
|
|
682
|
+
set: (t, n) => {
|
|
683
|
+
e = n;
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
})(), l, u = 0, d, f = 0, p = async (e) => {
|
|
687
|
+
if (d) return d;
|
|
688
|
+
d = (async () => {
|
|
689
|
+
let e = new AbortController(), t;
|
|
690
|
+
a > 0 && (t = setTimeout(() => e.abort(), a));
|
|
691
|
+
let n;
|
|
692
|
+
try {
|
|
693
|
+
n = await r(s, { signal: e.signal });
|
|
694
|
+
} catch (t) {
|
|
695
|
+
throw e.signal.aborted ? Error(`JWKS fetch timed out after ${a}ms`) : t;
|
|
696
|
+
} finally {
|
|
697
|
+
t && clearTimeout(t);
|
|
698
|
+
}
|
|
699
|
+
if (!n.ok) throw Error(`Failed to fetch JWKS: ${n.status} ${n.statusText}`);
|
|
700
|
+
let i = await n.json();
|
|
701
|
+
if (!i || typeof i != "object" || !Array.isArray(i.keys)) throw Error("Invalid JWKS");
|
|
702
|
+
return U(i);
|
|
703
|
+
})();
|
|
704
|
+
try {
|
|
705
|
+
let e = await d;
|
|
706
|
+
return l = e, await c.set(s, e), f = 0, i > 0 && (u = Date.now() + i), e;
|
|
707
|
+
} catch (t) {
|
|
708
|
+
if (!e || !l) throw t;
|
|
709
|
+
/* c8 ignore start - stale-on-failure is only reachable when ttl > 0 (auto-refresh path) */
|
|
710
|
+
if (f += 1, i > 0) {
|
|
711
|
+
let e = Math.min(Math.max(i, 3e4) * 2 ** (f - 1), 9e5);
|
|
712
|
+
u = Date.now() + e;
|
|
713
|
+
}
|
|
714
|
+
return console.warn(`JWKS refresh failed for "${s}", using stale cache.`, t), l;
|
|
715
|
+
} finally {
|
|
716
|
+
d = void 0;
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
l = await c.get(s), l ? (l = U(l), i > 0 && (u = Date.now() + i)) : l = await p(!1);
|
|
720
|
+
let m = {
|
|
721
|
+
async list() {
|
|
722
|
+
return i > 0 && Date.now() >= u && await p(!0), W(...l.keys);
|
|
723
|
+
},
|
|
724
|
+
async refresh() {
|
|
725
|
+
return await p(!1), m;
|
|
726
|
+
},
|
|
727
|
+
async key(e) {
|
|
728
|
+
let t = (await m.list()).find((t) => t.kid === e);
|
|
729
|
+
if (t) return W(t)[0];
|
|
730
|
+
},
|
|
731
|
+
async find(e) {
|
|
732
|
+
let t = await m.list(), n = Object.entries(e);
|
|
733
|
+
return n.length === 0 ? W(...t) : W(...t.filter((e) => n.every(([t, n]) => {
|
|
734
|
+
let r = e[t];
|
|
735
|
+
return Array.isArray(n) ? Array.isArray(r) && r.length === n.length && r.every((e, t) => e === n[t]) : r === n;
|
|
736
|
+
})));
|
|
737
|
+
},
|
|
738
|
+
async findFirst(e) {
|
|
739
|
+
return m.find(e).then(([e]) => e);
|
|
740
|
+
},
|
|
741
|
+
export() {
|
|
742
|
+
return l;
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
return m;
|
|
746
|
+
}, K = {
|
|
747
|
+
toKeyObject: H,
|
|
748
|
+
normalize: U,
|
|
749
|
+
fromWeb: G
|
|
750
|
+
};
|
|
751
|
+
//#endregion
|
|
752
|
+
export { k as AutodetectAlgorithm, V as JWK, K as JWKS, H as JWKSToKeyObject, F as JWT, D as SignatureAlgorithm, O as SupportedAlgorithms, d as base64Url, B as computeX5T, M as decode, I as exportJWK, G as fromWeb, z as getJWKThumbprint, L as importJWK, W as normalizeJWK, U as normalizeJWKS, N as sign, R as toPublicJWK, P as verify };
|
|
753
|
+
|
|
754
|
+
//# sourceMappingURL=index.js.map
|