unjwt 0.8.3 → 0.8.4
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/_chunks/_codec-jws.mjs +17 -17
- package/dist/_chunks/{jwk.mjs → _import-key.mjs} +36 -741
- package/dist/_chunks/_jwt-internal.mjs +19 -19
- package/dist/_chunks/jwe.d.mts +1 -0
- package/dist/_chunks/jwe.mjs +8 -7
- package/dist/_chunks/jwk.d.mts +205 -0
- package/dist/_chunks/jws.d.mts +4 -1
- package/dist/_chunks/jws.mjs +10 -10
- package/dist/_chunks/libs/unsecure.mjs +143 -130
- package/dist/adapters/elysia/index.d.mts +1 -1
- package/dist/adapters/elysia/index.mjs +3 -2
- package/dist/adapters/h3/index.d.mts +1 -1
- package/dist/adapters/h3/index.mjs +2 -1
- package/dist/adapters/h3v1/index.d.mts +1 -1
- package/dist/adapters/h3v1/index.mjs +2 -1
- package/dist/core/jwe.mjs +1 -1
- package/dist/core/jwk.d.mts +2 -204
- package/dist/core/jwk.mjs +712 -3
- package/dist/core/jws.mjs +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -1
- package/dist/session/index.d.mts +1 -1
- package/dist/session/index.mjs +2 -1
- package/package.json +3 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { sanitizeObjectCopy } from "./libs/unsecure.mjs";
|
|
2
2
|
import { JWTError, computeDurationInSeconds, expiredClaimMessage, isCryptoKey, isJWK, isJWKSet, isJWTError, isPlainObject, isPrivateJWK, isPublicJWK, isSymmetricJWK } from "./_jwt-internal.mjs";
|
|
3
|
-
import { importKey, quoteTokenValue } from "./
|
|
3
|
+
import { importKey, quoteTokenValue } from "./_import-key.mjs";
|
|
4
4
|
import { sign, verify } from "./jws.mjs";
|
|
5
5
|
import { decrypt, encrypt } from "./jwe.mjs";
|
|
6
6
|
const RESERVED_CLAIMS = [
|
|
@@ -46,8 +46,8 @@ function rethrowAsInvalidToken(error, options) {
|
|
|
46
46
|
const TOKEN = /^[!#$%&'*+\-.^_`|~\w]+$/;
|
|
47
47
|
const CHUNK_SUFFIX = /\.\d+$/;
|
|
48
48
|
function assertSessionName(name, options) {
|
|
49
|
-
if (!isToken(name)) throw invalidConfigError(`${options.prefix} Session "name" must be a cookie name (
|
|
50
|
-
if (CHUNK_SUFFIX.test(name)) throw invalidConfigError(`${options.prefix} Session "name"
|
|
49
|
+
if (!isToken(name)) throw invalidConfigError(`${options.prefix} Session "name" must be a valid cookie name (got ${quoteTokenValue(name)}).`);
|
|
50
|
+
if (CHUNK_SUFFIX.test(name)) throw invalidConfigError(`${options.prefix} Session "name" ${quoteTokenValue(name)} cannot end in a dot and digits.`);
|
|
51
51
|
}
|
|
52
52
|
function isToken(value) {
|
|
53
53
|
return typeof value === "string" && TOKEN.test(value);
|
|
@@ -57,7 +57,7 @@ function assertCookiePrefix(name, attrs, options) {
|
|
|
57
57
|
const host = lower.startsWith("__host-");
|
|
58
58
|
if (!host && !lower.startsWith("__secure-")) return;
|
|
59
59
|
const rule = host ? "\"__Host-\" cookie must be Secure, with Path=/ and no Domain" : "\"__Secure-\" cookie must be Secure";
|
|
60
|
-
if (attrs.secure === false || host && (attrs.domain !== void 0 || attrs.path !== void 0 && attrs.path !== "/")) throw invalidConfigError(`${options.prefix} Session ${quoteTokenValue(name)}: a ${rule}
|
|
60
|
+
if (attrs.secure === false || host && (attrs.domain !== void 0 || attrs.path !== void 0 && attrs.path !== "/")) throw invalidConfigError(`${options.prefix} Session ${quoteTokenValue(name)}: a ${rule}.`);
|
|
61
61
|
}
|
|
62
62
|
function assertRolling(config, options) {
|
|
63
63
|
const { rolling } = config;
|
|
@@ -65,10 +65,10 @@ function assertRolling(config, options) {
|
|
|
65
65
|
if (config.maxAge === void 0) throw invalidConfigError(`${options.prefix} "rolling" needs a "maxAge" to extend.`);
|
|
66
66
|
if (rolling === true) return;
|
|
67
67
|
if (!isExpiresIn(rolling)) throw new JWTError(`${options.prefix} "rolling" must be true or a duration.`, "ERR_INVALID_OPTION");
|
|
68
|
-
if (computeDurationInSeconds(rolling) >= computeDurationInSeconds(config.maxAge)) throw invalidConfigError(`${options.prefix} "rolling" must be shorter than "maxAge"
|
|
68
|
+
if (computeDurationInSeconds(rolling) >= computeDurationInSeconds(config.maxAge)) throw invalidConfigError(`${options.prefix} "rolling" must be shorter than "maxAge".`);
|
|
69
69
|
}
|
|
70
70
|
function assertKeyMaterial(key, options) {
|
|
71
|
-
if (typeof key === "string") throw invalidKeyError(`${options.prefix} Session "key"
|
|
71
|
+
if (typeof key === "string") throw invalidKeyError(`${options.prefix} Session "key" cannot be a string, use deriveJWKFromPassword().`);
|
|
72
72
|
if (!key) throw invalidKeyError(`${options.prefix} Session "key" is required.`);
|
|
73
73
|
}
|
|
74
74
|
async function assertImportableKey(key, options) {
|
|
@@ -109,7 +109,7 @@ function sessionRequiredClaims(configured, options) {
|
|
|
109
109
|
return [...required];
|
|
110
110
|
}
|
|
111
111
|
function sanitizeSessionUpdate(update, options) {
|
|
112
|
-
if (!isPlainObject(update)) throw new JWTError(`${options.prefix} Session data must be a plain object
|
|
112
|
+
if (!isPlainObject(update)) throw new JWTError(`${options.prefix} Session data must be a plain object.`, "ERR_INVALID_OPTION");
|
|
113
113
|
const sanitized = Object.create(null);
|
|
114
114
|
for (const key of Object.keys(update)) {
|
|
115
115
|
if (FORBIDDEN_KEYS.includes(key)) throw new JWTError(`${options.prefix} Session data cannot carry the key "${key}".`, "ERR_INVALID_OPTION");
|
|
@@ -205,7 +205,7 @@ function assertKeyPair(pair, options) {
|
|
|
205
205
|
if (!options.isPublic(pair.publicKey)) throw invalidKeyError(`${prefix} Invalid ${family} key: "publicKey" must be ${options.publicHalf}.`, pair);
|
|
206
206
|
}
|
|
207
207
|
function assertPinnedCryptoKey(key, options) {
|
|
208
|
-
if (isCryptoKey(key) && !options.pinned) throw invalidConfigError(`${options.prefix} A CryptoKey session key carries no algorithm
|
|
208
|
+
if (isCryptoKey(key) && !options.pinned) throw invalidConfigError(`${options.prefix} A CryptoKey session key carries no algorithm, set ${options.hint}.`);
|
|
209
209
|
}
|
|
210
210
|
function sessionPayload(state) {
|
|
211
211
|
const iat = Math.floor(state.createdAt / 1e3);
|
|
@@ -219,7 +219,7 @@ function sessionPayload(state) {
|
|
|
219
219
|
}
|
|
220
220
|
function assertNotFromTheFuture(payload, options) {
|
|
221
221
|
const tolerance = options.clockTolerance === void 0 ? 0 : computeDurationInSeconds(options.clockTolerance);
|
|
222
|
-
if (payload.iat > Math.floor(options.now / 1e3) + tolerance) throw invalidTokenError(`${options.prefix} Invalid session token:
|
|
222
|
+
if (payload.iat > Math.floor(options.now / 1e3) + tolerance) throw invalidTokenError(`${options.prefix} Invalid session token: "iat" is in the future (${(/* @__PURE__ */ new Date(payload.iat * 1e3)).toISOString()}).`);
|
|
223
223
|
}
|
|
224
224
|
function openedSession(payload) {
|
|
225
225
|
const data = Object.create(null);
|
|
@@ -294,7 +294,7 @@ function getEncryptKey(config, prefix) {
|
|
|
294
294
|
assertJWEKeyPair(key, prefix);
|
|
295
295
|
resolved = key.publicKey;
|
|
296
296
|
}
|
|
297
|
-
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWE key
|
|
297
|
+
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWE key, expected a JWK or a CryptoKey.`, key);
|
|
298
298
|
assertPinnedAlgEnc(resolved, config, prefix);
|
|
299
299
|
return resolved;
|
|
300
300
|
}
|
|
@@ -307,7 +307,7 @@ function getDecryptKey(config, prefix) {
|
|
|
307
307
|
assertJWEKeyPair(key, prefix);
|
|
308
308
|
resolved = key.privateKey;
|
|
309
309
|
}
|
|
310
|
-
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWE key
|
|
310
|
+
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWE key, expected a JWK, a private JWK or a CryptoKey.`, key);
|
|
311
311
|
assertPinnedAlgEnc(resolved, config, prefix);
|
|
312
312
|
return resolved;
|
|
313
313
|
}
|
|
@@ -448,7 +448,7 @@ function resolveTransport(driver, event, options) {
|
|
|
448
448
|
return transport;
|
|
449
449
|
}
|
|
450
450
|
function assertTokenSource(transport, options) {
|
|
451
|
-
if (!transport.read) throw invalidConfigError(`${options.prefix} Session has no token source
|
|
451
|
+
if (!transport.read) throw invalidConfigError(`${options.prefix} Session has no token source, enable "cookie" or "sessionHeader".`);
|
|
452
452
|
}
|
|
453
453
|
function assertWritable(transport, options) {
|
|
454
454
|
const { operation, prefix } = options;
|
|
@@ -458,7 +458,7 @@ function assertWritable(transport, options) {
|
|
|
458
458
|
function assertSessionHeader(header, options) {
|
|
459
459
|
if (header === void 0 || typeof header === "boolean") return;
|
|
460
460
|
if (isToken(header)) return;
|
|
461
|
-
throw invalidConfigError(`${options.prefix} Session "sessionHeader" must be true, false or a header name
|
|
461
|
+
throw invalidConfigError(`${options.prefix} Session "sessionHeader" must be true, false or a header name (got ${quoteTokenValue(header)}).`);
|
|
462
462
|
}
|
|
463
463
|
function sessionHeaderName(sessionName, configured) {
|
|
464
464
|
if (typeof configured === "string") return configured.toLowerCase();
|
|
@@ -561,7 +561,7 @@ function claimSessionName(record, options) {
|
|
|
561
561
|
return;
|
|
562
562
|
}
|
|
563
563
|
if (held === family) return;
|
|
564
|
-
throw invalidConfigError(`${prefix} Session name "${name}" is already used by a ${held.toUpperCase()} session on this request
|
|
564
|
+
throw invalidConfigError(`${prefix} Session name "${name}" is already used by a ${held.toUpperCase()} session on this request.`);
|
|
565
565
|
}
|
|
566
566
|
const kSessionPending = Symbol("unjwt_session_pending");
|
|
567
567
|
function sessionInstant(source) {
|
|
@@ -914,7 +914,7 @@ function getSignKey(config, prefix) {
|
|
|
914
914
|
assertJWSKeyPair(key, prefix);
|
|
915
915
|
resolved = key.privateKey;
|
|
916
916
|
}
|
|
917
|
-
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWS key
|
|
917
|
+
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWS key, expected a symmetric JWK, a private JWK or a CryptoKey.`, key);
|
|
918
918
|
assertPinnedAlg(resolved, config, prefix);
|
|
919
919
|
return resolved;
|
|
920
920
|
}
|
|
@@ -927,7 +927,7 @@ function getVerifyKey(config, prefix) {
|
|
|
927
927
|
assertJWSKeyPair(key, prefix);
|
|
928
928
|
resolved = Array.isArray(key.publicKey) ? { keys: key.publicKey } : key.publicKey;
|
|
929
929
|
}
|
|
930
|
-
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWS key
|
|
930
|
+
if (!resolved) throw invalidKeyError(`${prefix} Invalid JWS key, expected a symmetric JWK, a public JWK/set or a CryptoKey.`, key);
|
|
931
931
|
assertPinnedAlg(resolved, config, prefix);
|
|
932
932
|
return resolved;
|
|
933
933
|
}
|
|
@@ -936,7 +936,7 @@ function assertJWSKeyPair(key, prefix) {
|
|
|
936
936
|
prefix,
|
|
937
937
|
family: "JWS",
|
|
938
938
|
isPublic: (half) => isCryptoKey(half) || isPublicJWK(half) || isPublicKeyList(Array.isArray(half) ? half : isJWKSet(half) ? half.keys : void 0),
|
|
939
|
-
publicHalf: "a public JWK, a non-empty
|
|
939
|
+
publicHalf: "a public JWK, a non-empty JWK set or a CryptoKey"
|
|
940
940
|
});
|
|
941
941
|
}
|
|
942
942
|
function isPublicKeyList(keys) {
|