unjwt 0.8.1 → 0.8.3

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.
Files changed (37) hide show
  1. package/README.md +4 -4
  2. package/dist/THIRD-PARTY-LICENSES.md.gz +0 -0
  3. package/dist/_chunks/_codec-jwe.d.mts +101 -22
  4. package/dist/_chunks/_codec-jws.mjs +306 -232
  5. package/dist/_chunks/_cookie-attributes.d.mts +12 -0
  6. package/dist/_chunks/_jwt-internal.mjs +9 -6
  7. package/dist/_chunks/digest.d.mts +8 -0
  8. package/dist/_chunks/{algorithms.mjs → digest.mjs} +78 -8
  9. package/dist/_chunks/index.d.mts +313 -268
  10. package/dist/_chunks/index2.d.mts +2 -1
  11. package/dist/_chunks/index3.d.mts +1 -0
  12. package/dist/_chunks/jwe.d.mts +4 -4
  13. package/dist/_chunks/jwe.mjs +21 -3
  14. package/dist/_chunks/jwk.mjs +219 -173
  15. package/dist/_chunks/jws.d.mts +10 -10
  16. package/dist/_chunks/jws.mjs +18 -6
  17. package/dist/_chunks/jwt.d.mts +2 -1
  18. package/dist/_chunks/libs/cookie-es.mjs +255 -0
  19. package/dist/adapters/elysia/index.d.mts +32 -15
  20. package/dist/adapters/elysia/index.mjs +46 -67
  21. package/dist/adapters/h3/index.d.mts +135 -0
  22. package/dist/adapters/h3/index.mjs +119 -0
  23. package/dist/adapters/h3v1/index.d.mts +100 -27
  24. package/dist/adapters/h3v1/index.mjs +59 -76
  25. package/dist/core/jwe.d.mts +2 -2
  26. package/dist/core/jwk.d.mts +22 -14
  27. package/dist/core/jwk.mjs +2 -2
  28. package/dist/core/jws.d.mts +2 -2
  29. package/dist/core/utils/index.d.mts +2 -1
  30. package/dist/core/utils/index.mjs +2 -2
  31. package/dist/index.d.mts +4 -3
  32. package/dist/index.mjs +3 -3
  33. package/dist/session/index.d.mts +44 -0
  34. package/dist/session/index.mjs +113 -0
  35. package/package.json +37 -18
  36. package/dist/adapters/h3v2/index.d.mts +0 -65
  37. package/dist/adapters/h3v2/index.mjs +0 -139
@@ -0,0 +1,12 @@
1
+ /** The `Set-Cookie` attributes of a session cookie (RFC 6265, RFC 6265bis, CHIPS). */
2
+ export interface CookieAttributes {
3
+ domain?: string;
4
+ expires?: Date;
5
+ httpOnly?: boolean;
6
+ maxAge?: number;
7
+ path?: string;
8
+ priority?: "low" | "medium" | "high";
9
+ sameSite?: boolean | "lax" | "strict" | "none";
10
+ secure?: boolean;
11
+ partitioned?: boolean;
12
+ }
@@ -283,29 +283,32 @@ function getPlaintextBytes(payload) {
283
283
  throw new JWTError("Plaintext must be a string, Uint8Array, or a JSON-serializable object.", "ERR_INVALID_OPTION");
284
284
  }
285
285
  function computeJwtTimeClaims(payload, options) {
286
- const { currentDate, expiresIn, expiresAt, notBeforeIn, notBeforeAt } = options ?? {};
286
+ const { currentDate, issuedAt, expiresIn, expiresAt, notBeforeIn, notBeforeAt } = options ?? {};
287
+ if (issuedAt !== void 0 && typeof issuedAt !== "boolean" && !(issuedAt instanceof Date)) throw new JWTError("\"issuedAt\" must be a boolean or a Date.", "ERR_INVALID_OPTION");
287
288
  if (expiresIn !== void 0 && expiresAt !== void 0) throw new JWTError("\"expiresIn\" and \"expiresAt\" are mutually exclusive; pass only one.", "ERR_JWT_CLAIM_INVALID");
288
289
  if (notBeforeIn !== void 0 && notBeforeAt !== void 0) throw new JWTError("\"notBeforeIn\" and \"notBeforeAt\" are mutually exclusive; pass only one.", "ERR_JWT_CLAIM_INVALID");
289
290
  const hasExpHint = expiresIn !== void 0 || expiresAt !== void 0;
290
291
  const hasNbfHint = notBeforeIn !== void 0 || notBeforeAt !== void 0;
291
- if (!hasExpHint && !hasNbfHint) return void 0;
292
+ const hasIatHint = issuedAt === true || issuedAt instanceof Date;
293
+ if (!hasExpHint && !hasNbfHint && !hasIatHint) return void 0;
292
294
  if (!payload || typeof payload !== "object" || payload instanceof Uint8Array) return void 0;
293
295
  const wantsExp = hasExpHint && (!("exp" in payload) || payload.exp === void 0);
294
296
  const wantsNbf = hasNbfHint && (!("nbf" in payload) || payload.nbf === void 0);
295
- if (!wantsExp && !wantsNbf) return void 0;
297
+ const wantsIat = hasIatHint && (!("iat" in payload) || payload.iat === void 0);
298
+ if (!wantsExp && !wantsNbf && !wantsIat) return void 0;
296
299
  const now = Math.round((currentDate ?? /* @__PURE__ */ new Date()).getTime() / 1e3);
297
300
  const claims = { ...payload };
298
- claims.iat ||= now;
301
+ claims.iat ||= issuedAt instanceof Date ? Math.floor(_instantOf(issuedAt, "issuedAt") / 1e3) : now;
299
302
  if (wantsExp) {
300
303
  if (expiresAt !== void 0) claims.exp = Math.floor(_instantOf(expiresAt, "expiresAt") / 1e3);
301
- else if (expiresIn !== void 0) claims.exp = claims.iat + computeDurationInSeconds(expiresIn);
304
+ else if (expiresIn !== void 0) claims.exp = now + computeDurationInSeconds(expiresIn);
302
305
  }
303
306
  if (wantsNbf) {
304
307
  if (notBeforeAt !== void 0) claims.nbf = Math.floor(_instantOf(notBeforeAt, "notBeforeAt") / 1e3);
305
308
  else if (notBeforeIn !== void 0) {
306
309
  const offset = parseDurationSeconds(notBeforeIn);
307
310
  if (offset < 0) throw new JWTError("\"notBeforeIn\" must be zero or a positive duration.", "ERR_JWT_CLAIM_INVALID");
308
- claims.nbf = claims.iat + offset;
311
+ claims.nbf = now + offset;
309
312
  }
310
313
  }
311
314
  return claims;
@@ -0,0 +1,8 @@
1
+ /** Hash functions the JOSE specs name for digests carried in tokens. */
2
+ export type DigestHash = "SHA-256" | "SHA-384" | "SHA-512";
3
+ /**
4
+ * The base64url digest of text or bytes, SHA-256 unless `hash` says otherwise: a DPoP `ath`
5
+ * (RFC 9449 §4.2) over the access token, an `x5t#S256` over a certificate, the last step of a
6
+ * JWK thumbprint. Text is digested as UTF-8.
7
+ */
8
+ export declare function digestUrl(data: string | Uint8Array<ArrayBuffer>, hash?: DigestHash): Promise<string>;
@@ -1,4 +1,5 @@
1
- import { JWTError, isCryptoKey, isCryptoKeyPair, isJWK, isJWKSet } from "./_jwt-internal.mjs";
1
+ import { textEncoder } from "./libs/unsecure.mjs";
2
+ import { JWTError, base64UrlStringify, isCryptoKey, isCryptoKeyPair, isJWK, isJWKSet } from "./_jwt-internal.mjs";
2
3
  const ECDSA_CURVES = /* @__PURE__ */ Object.freeze({
3
4
  ES256: "P-256",
4
5
  ES384: "P-384",
@@ -7,8 +8,26 @@ const ECDSA_CURVES = /* @__PURE__ */ Object.freeze({
7
8
  function jwsHashOf(alg) {
8
9
  return `SHA-${alg.slice(-3)}`;
9
10
  }
11
+ const RSA_OAEP_HASH = /* @__PURE__ */ Object.freeze({
12
+ "RSA-OAEP": "SHA-1",
13
+ "RSA-OAEP-256": "SHA-256",
14
+ "RSA-OAEP-384": "SHA-384",
15
+ "RSA-OAEP-512": "SHA-512"
16
+ });
10
17
  function rsaOaepHashOf(alg) {
11
- return `SHA-${Number.parseInt(alg.slice(9), 10) || 1}`;
18
+ return RSA_OAEP_HASH[alg];
19
+ }
20
+ function pbes2HashOf(alg) {
21
+ return `SHA-${alg.slice(8, 11)}`;
22
+ }
23
+ const SHA_BITS = /* @__PURE__ */ Object.freeze({
24
+ "SHA-1": 1,
25
+ "SHA-256": 256,
26
+ "SHA-384": 384,
27
+ "SHA-512": 512
28
+ });
29
+ function shaBitsOf(sha) {
30
+ return SHA_BITS[sha];
12
31
  }
13
32
  function aesBitsOf(alg) {
14
33
  return Number.parseInt(alg.slice(1, 4), 10);
@@ -51,12 +70,62 @@ const PBES2_ALGORITHMS = [
51
70
  "PBES2-HS384+A192KW",
52
71
  "PBES2-HS512+A256KW"
53
72
  ];
73
+ const PBES2_ALGORITHM_SET = /* @__PURE__ */ new Set(PBES2_ALGORITHMS);
74
+ function isPBES2Algorithm(alg) {
75
+ return PBES2_ALGORITHM_SET.has(alg);
76
+ }
77
+ const JWS_ALGORITHMS = /* @__PURE__ */ new Set(Object.keys({
78
+ HS256: true,
79
+ HS384: true,
80
+ HS512: true,
81
+ RS256: true,
82
+ RS384: true,
83
+ RS512: true,
84
+ PS256: true,
85
+ PS384: true,
86
+ PS512: true,
87
+ ES256: true,
88
+ ES384: true,
89
+ ES512: true,
90
+ Ed25519: true,
91
+ EdDSA: true
92
+ }));
93
+ function isJWSAlgorithm(alg) {
94
+ return JWS_ALGORITHMS.has(alg);
95
+ }
96
+ const KEY_MANAGEMENT_ALGORITHMS = /* @__PURE__ */ new Set(Object.keys({
97
+ "dir": true,
98
+ "A128KW": true,
99
+ "A192KW": true,
100
+ "A256KW": true,
101
+ "A128GCMKW": true,
102
+ "A192GCMKW": true,
103
+ "A256GCMKW": true,
104
+ "PBES2-HS256+A128KW": true,
105
+ "PBES2-HS384+A192KW": true,
106
+ "PBES2-HS512+A256KW": true,
107
+ "RSA-OAEP": true,
108
+ "RSA-OAEP-256": true,
109
+ "RSA-OAEP-384": true,
110
+ "RSA-OAEP-512": true,
111
+ "ECDH-ES": true,
112
+ "ECDH-ES+A128KW": true,
113
+ "ECDH-ES+A192KW": true,
114
+ "ECDH-ES+A256KW": true
115
+ }));
116
+ function isKeyManagementAlgorithm(alg) {
117
+ return KEY_MANAGEMENT_ALGORITHMS.has(alg);
118
+ }
54
119
  const ECDH_ES_ALGORITHMS = [
55
120
  "ECDH-ES",
56
121
  "ECDH-ES+A128KW",
57
122
  "ECDH-ES+A192KW",
58
123
  "ECDH-ES+A256KW"
59
124
  ];
125
+ const ECDH_ES_ALGORITHM_SET = /* @__PURE__ */ new Set(ECDH_ES_ALGORITHMS);
126
+ function isECDHESAlgorithm(alg) {
127
+ return ECDH_ES_ALGORITHM_SET.has(alg);
128
+ }
60
129
  function inferJWSAllowedAlgorithms(key, options) {
61
130
  if (!key || typeof key === "function") return void 0;
62
131
  if (typeof key === "string" || key instanceof Uint8Array) return void 0;
@@ -92,7 +161,7 @@ function isEd25519Signature(alg) {
92
161
  }
93
162
  function jwsAlgsFromJWK(jwk) {
94
163
  if (jwk.alg && isEd25519Signature(jwk.alg)) return ["EdDSA", "Ed25519"];
95
- if (jwk.alg) return declaredAlgorithm(jwk.alg);
164
+ if (jwk.alg) return isJWSAlgorithm(jwk.alg) ? [jwk.alg] : void 0;
96
165
  if (jwk.kty === "EC") {
97
166
  const crv = jwk.crv;
98
167
  if (crv === "P-256") return ["ES256"];
@@ -105,7 +174,7 @@ function jwsAlgsFromJWK(jwk) {
105
174
  }
106
175
  function jweAlgsFromJWK(jwk) {
107
176
  if (jwk.kty === "oct") return jweAlgsFromOctJWK(jwk);
108
- if (jwk.alg) return declaredAlgorithm(jwk.alg);
177
+ if (jwk.alg) return isKeyManagementAlgorithm(jwk.alg) ? [jwk.alg] : void 0;
109
178
  if (jwk.kty === "EC") {
110
179
  const crv = jwk.crv;
111
180
  if (crv === "P-256" || crv === "P-384" || crv === "P-521") return [...ECDH_ES_ALGORITHMS];
@@ -118,7 +187,7 @@ function jweAlgsFromOctJWK(jwk) {
118
187
  const alg = jwk.alg;
119
188
  if (!alg) return void 0;
120
189
  if (isContentEncryptionAlgorithm(alg)) return ["dir"];
121
- return declaredAlgorithm(alg);
190
+ return isKeyManagementAlgorithm(alg) ? [alg] : void 0;
122
191
  }
123
192
  function isContentEncryptionAlgorithm(alg) {
124
193
  return CONTENT_ENCRYPTION_ALGORITHMS.has(alg);
@@ -180,7 +249,8 @@ function jwsHashBits(hashName) {
180
249
  if (hashName === "SHA-384") return "384";
181
250
  if (hashName === "SHA-512") return "512";
182
251
  }
183
- function declaredAlgorithm(alg) {
184
- return [alg];
252
+ async function digestUrl(data, hash = "SHA-256") {
253
+ const bytes = typeof data === "string" ? textEncoder.encode(data) : data;
254
+ return base64UrlStringify(new Uint8Array(await crypto.subtle.digest(hash, bytes)));
185
255
  }
186
- export { ECDSA_CURVES, PBES2_ALGORITHMS, aesBitsOf, checkKeyUsage, cryptoKeyCurve, hashBitsOf, inferJWEAllowedAlgorithms, inferJWSAllowedAlgorithms, innerKeyWrapAlg, isAlgorithm, isContentEncryptionAlgorithm, isEd25519Signature, jwsHashOf, lengthOf, modulusLengthOf, namedCurveOf, rsaOaepHashOf, unusableKey };
256
+ export { ECDSA_CURVES, PBES2_ALGORITHMS, aesBitsOf, checkKeyUsage, cryptoKeyCurve, digestUrl, hashBitsOf, inferJWEAllowedAlgorithms, inferJWSAllowedAlgorithms, innerKeyWrapAlg, isAlgorithm, isContentEncryptionAlgorithm, isECDHESAlgorithm, isEd25519Signature, isJWSAlgorithm, isKeyManagementAlgorithm, isPBES2Algorithm, jwsHashOf, lengthOf, modulusLengthOf, namedCurveOf, pbes2HashOf, rsaOaepHashOf, shaBitsOf, unusableKey };