unjwt 0.5.22 → 0.5.23

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/h3.d.mts CHANGED
@@ -9,7 +9,7 @@ export { d as deriveJWKFromPassword, e as exportJWKToPEM, g as generateJWK, i as
9
9
 
10
10
  /**
11
11
  * This is a fork of h3 library's session utility functions.
12
- * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/test/session.test.ts
12
+ * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
13
13
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
14
14
  */
15
15
 
@@ -24,11 +24,11 @@ interface SessionJWE<T extends SessionDataT$1 = SessionDataT$1> {
24
24
  [kGetSessionPromise$1]?: Promise<SessionJWE<T>>;
25
25
  }
26
26
  interface SessionHooksJWE {
27
- onRead?: (session: SessionJWE, event: H3Event) => void | Promise<void>;
28
- onUpdate?: (session: SessionJWE, event: H3Event) => void | Promise<void>;
29
- onClear?: (event: H3Event) => void | Promise<void>;
30
- onExpire?: (event: H3Event, error: any | undefined) => void | Promise<void>;
31
- onError?: (event: H3Event, error: any) => void | Promise<void>;
27
+ onRead?: (session: SessionJWE, event: H3Event, config: SessionConfigJWE) => void | Promise<void>;
28
+ onUpdate?: (session: SessionJWE, event: H3Event, config: SessionConfigJWE) => void | Promise<void>;
29
+ onClear?: (event: H3Event, config: Partial<SessionConfigJWE>) => void | Promise<void>;
30
+ onExpire?: (event: H3Event, error: any | undefined, config: SessionConfigJWE) => void | Promise<void>;
31
+ onError?: (event: H3Event, error: any, config: SessionConfigJWE) => void | Promise<void>;
32
32
  }
33
33
  interface SessionManager<T extends SessionDataT$1 = SessionDataT$1> {
34
34
  readonly id: string | undefined;
@@ -39,8 +39,13 @@ interface SessionManager<T extends SessionDataT$1 = SessionDataT$1> {
39
39
  clear: () => Promise<SessionManager<T>>;
40
40
  }
41
41
  interface SessionConfigJWE {
42
- /** Shared secret used, string for PBES2 or Json Web Key (JWK) */
43
- secret: string | JWK_Symmetric | {
42
+ /** @deprecated use `key` instead */
43
+ secret?: string | JWK_Symmetric | {
44
+ privateKey: JWK_Private | JWK_Symmetric;
45
+ publicKey?: JWK_Public;
46
+ };
47
+ /** Shared key used, string for PBES2 or Json Web Key (JWK) */
48
+ key: string | JWK_Symmetric | JWK_Private | {
44
49
  privateKey: JWK_Private | JWK_Symmetric;
45
50
  publicKey?: JWK_Public;
46
51
  };
@@ -52,8 +57,6 @@ interface SessionConfigJWE {
52
57
  cookie?: false | CookieSerializeOptions;
53
58
  /** Default is x-h3-session / x-{name}-session */
54
59
  sessionHeader?: false | string;
55
- /** Optional WebCrypto implementation override */
56
- crypto?: Crypto;
57
60
  /** Default is crypto.randomUUID */
58
61
  generateId?: () => string;
59
62
  /** JWE configuration overrides */
@@ -111,7 +114,7 @@ declare function clearJWESession(event: H3Event, config: Partial<SessionConfigJW
111
114
 
112
115
  /**
113
116
  * This is a fork of h3 library's session utility functions.
114
- * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/test/session.test.ts
117
+ * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
115
118
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
116
119
  */
117
120
 
@@ -125,11 +128,11 @@ interface SessionJWS<T extends SessionDataT = SessionDataT> {
125
128
  [kGetSessionPromise]?: Promise<SessionJWS<T>>;
126
129
  }
127
130
  interface SessionHooksJWS {
128
- onRead?: (session: SessionJWS, event: H3Event) => void | Promise<void>;
129
- onUpdate?: (session: SessionJWS, event: H3Event) => void | Promise<void>;
130
- onClear?: (event: H3Event) => void | Promise<void>;
131
- onExpire?: (event: H3Event, error: any | undefined) => void | Promise<void>;
132
- onError?: (event: H3Event, error: any) => void | Promise<void>;
131
+ onRead?: (session: SessionJWS, event: H3Event, config: SessionConfigJWS) => void | Promise<void>;
132
+ onUpdate?: (session: SessionJWS, event: H3Event, config: SessionConfigJWS) => void | Promise<void>;
133
+ onClear?: (event: H3Event, config: Partial<SessionConfigJWS>) => void | Promise<void>;
134
+ onExpire?: (event: H3Event, error: any | undefined, config: SessionConfigJWS) => void | Promise<void>;
135
+ onError?: (event: H3Event, error: any, config: SessionConfigJWS) => void | Promise<void>;
133
136
  }
134
137
  interface SessionConfigJWS {
135
138
  /**
@@ -147,8 +150,6 @@ interface SessionConfigJWS {
147
150
  cookie?: false | CookieSerializeOptions;
148
151
  /** Custom header (false to disable header lookup) */
149
152
  sessionHeader?: false | string;
150
- /** Provide a custom WebCrypto (if needed for algorithm operations) */
151
- crypto?: Crypto;
152
153
  /** Custom ID generator (defaults to crypto.randomUUID) */
153
154
  generateId?: () => string;
154
155
  /** JWS customization */
package/dist/h3.mjs CHANGED
@@ -1,13 +1,13 @@
1
- export { k as deriveJWKFromPassword, h as exportJWKToPEM, c as generateJWK, f as importJWKFromPEM } from './shared/unjwt.Vg02PZWw.mjs';
1
+ export { k as deriveJWKFromPassword, h as exportJWKToPEM, c as generateJWK, f as importJWKFromPEM } from './shared/unjwt.epPK1KFr.mjs';
2
2
  import { isEvent, setCookie } from 'h3';
3
3
  import { parse } from 'cookie-es';
4
- import { e as encrypt, d as decrypt } from './shared/unjwt.CXl9FD-V.mjs';
5
- import { p as isSymmetricJWK, q as isPrivateJWK, u as isAsymmetricJWK } from './shared/unjwt.DCiTNyCM.mjs';
6
- import { s as sign, v as verify } from './shared/unjwt.DmRAjMp8.mjs';
4
+ import { e as encrypt, d as decrypt } from './shared/unjwt.CiBEuvtQ.mjs';
5
+ import { p as isSymmetricJWK, q as isPrivateJWK, u as isPublicJWK } from './shared/unjwt.C86hA0o-.mjs';
6
+ import { s as sign, v as verify } from './shared/unjwt.D-FATaw1.mjs';
7
7
 
8
8
  /**
9
9
  * This is a fork of h3 library's session utility functions.
10
- * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/test/session.test.ts
10
+ * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
11
11
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
12
12
  */
13
13
  const kGetSessionPromise$1 = Symbol("h3_jwe_getSession");
@@ -57,22 +57,15 @@ async function getJWESession(event, config) {
57
57
  }
58
58
  const existingSession = event.context.sessions[sessionName];
59
59
  if (existingSession) {
60
- if (existingSession.expiresAt === void 0) {
61
- const session2 = existingSession[kGetSessionPromise$1] || existingSession;
62
- await config.hooks?.onRead?.(await session2, event);
63
- return session2;
64
- } else {
65
- if (existingSession.expiresAt < Date.now() && isEvent(event)) {
66
- await config.hooks?.onExpire?.(event, void 0);
67
- return clearJWESession(event, config).then(
68
- () => getJWESession(event, config)
69
- );
70
- } else {
71
- const session2 = existingSession[kGetSessionPromise$1] || existingSession;
72
- await config.hooks?.onRead?.(await session2, event);
73
- return session2;
74
- }
60
+ const session2 = existingSession[kGetSessionPromise$1] ? await existingSession[kGetSessionPromise$1] : existingSession;
61
+ if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && isEvent(event)) {
62
+ await config.hooks?.onExpire?.(event, void 0, config);
63
+ return clearJWESession(event, config).then(
64
+ () => getJWESession(event, config)
65
+ );
75
66
  }
67
+ await config.hooks?.onRead?.(session2, event, config);
68
+ return session2;
76
69
  }
77
70
  const session = {
78
71
  id: "",
@@ -97,14 +90,11 @@ async function getJWESession(event, config) {
97
90
  }
98
91
  if (jweToken) {
99
92
  const promise = unsealJWESession(event, config, jweToken).catch(async (error_) => {
100
- if (error_ instanceof Error) {
101
- const message = error_.message;
102
- if (message.includes("Token has expired") || message.includes("Token is too old")) {
103
- await config.hooks?.onExpire?.(event, error_);
104
- return void 0;
105
- }
93
+ if (error_ instanceof Error && (error_.message.includes("Token has expired") || error_.message.includes("Token is too old"))) {
94
+ await config.hooks?.onExpire?.(event, error_, config);
95
+ return void 0;
106
96
  }
107
- await config.hooks?.onError?.(event, error_);
97
+ await config.hooks?.onError?.(event, error_, config);
108
98
  return void 0;
109
99
  }).then((unsealed) => {
110
100
  if (unsealed) {
@@ -122,13 +112,12 @@ async function getJWESession(event, config) {
122
112
  "Cannot initialize a new session. Use `useSession(event)` within the main handler."
123
113
  );
124
114
  }
125
- session.id = config.generateId?.() ?? (config.crypto || crypto).randomUUID();
126
- session.createdAt = config.jwe?.encryptOptions?.currentDate === void 0 ? Date.now() : config.jwe.encryptOptions.currentDate.getTime();
115
+ session.id = config.generateId?.() ?? crypto.randomUUID();
116
+ session.createdAt = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
127
117
  session.expiresAt = config.maxAge ? session.createdAt + config.maxAge * 1e3 : void 0;
128
- session.data = /* @__PURE__ */ Object.create(null);
129
118
  await updateJWESession(event, config);
130
119
  }
131
- await config.hooks?.onRead?.(session, event);
120
+ await config.hooks?.onRead?.(session, event, config);
132
121
  return session;
133
122
  }
134
123
  function _getReqHeader$1(event, name) {
@@ -150,7 +139,7 @@ async function updateJWESession(event, config, update) {
150
139
  }
151
140
  if (update) {
152
141
  Object.assign(session.data, update);
153
- await config.hooks?.onUpdate?.(session, event);
142
+ await config.hooks?.onUpdate?.(session, event, config);
154
143
  }
155
144
  if (config.cookie !== false) {
156
145
  const sealed = await sealJWESession(event, config);
@@ -166,12 +155,7 @@ async function updateJWESession(event, config, update) {
166
155
  return session;
167
156
  }
168
157
  async function sealJWESession(event, config) {
169
- const key = getEncryptKey(config.secret);
170
- if (typeof key !== "string" && !isSymmetricJWK(key) && !isPrivateJWK(key)) {
171
- throw new Error(
172
- "Session: JWE secret must be a password string or a private JWK."
173
- );
174
- }
158
+ const key = getEncryptKey(config.key || config.secret);
175
159
  const sessionName = config.name || DEFAULT_NAME$1;
176
160
  const session = event.context.sessions?.[sessionName] || await getJWESession(event, config);
177
161
  const iatSeconds = Math.floor(session.createdAt / 1e3);
@@ -184,25 +168,30 @@ async function sealJWESession(event, config) {
184
168
  if (expSeconds) {
185
169
  payload.exp = expSeconds;
186
170
  }
171
+ let typ = void 0;
172
+ if (config.jwe?.encryptOptions?.protectedHeader?.typ && typeof config.jwe.encryptOptions.protectedHeader.typ === "string" && config.jwe.encryptOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
173
+ typ = config.jwe.encryptOptions.protectedHeader.typ;
174
+ }
187
175
  const token = await encrypt(payload, key, {
188
176
  ...config.jwe?.encryptOptions,
177
+ expiresIn: void 0,
178
+ // controlled via 'exp' claim
189
179
  protectedHeader: {
190
180
  ...config.jwe?.encryptOptions?.protectedHeader,
191
- typ: "JWT",
181
+ kid: typeof key === "string" ? void 0 : key.kid,
182
+ typ: typ || "JWT",
192
183
  cty: "application/json"
193
184
  }
194
185
  });
195
186
  return token;
196
187
  }
197
188
  async function unsealJWESession(_event, config, sealed) {
198
- const key = getDecryptKey(config.secret);
199
- if (typeof key !== "string" && !isSymmetricJWK(key) && !isPrivateJWK(key)) {
200
- throw new Error(
201
- "Session: JWE secret must be a password string or a private JWK."
202
- );
203
- }
189
+ const key = getDecryptKey(config.key || config.secret);
204
190
  const alg = config.jwe?.encryptOptions?.alg;
205
191
  const enc = config.jwe?.encryptOptions?.enc;
192
+ if (config.jwe?.encryptOptions?.protectedHeader?.typ && typeof config.jwe.encryptOptions.protectedHeader.typ === "string" && config.jwe.encryptOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
193
+ config.jwe.encryptOptions.protectedHeader.typ;
194
+ }
206
195
  const { payload } = await decrypt(sealed, key, {
207
196
  ...config.jwe?.decryptOptions,
208
197
  requiredClaims: [
@@ -243,32 +232,57 @@ async function clearJWESession(event, config) {
243
232
  setCookie(event, sessionName, "", {
244
233
  ...DEFAULT_COOKIE$1,
245
234
  ...config.cookie,
246
- // Optionally set expires in the past
247
235
  expires: /* @__PURE__ */ new Date(0),
248
236
  maxAge: void 0
249
237
  });
250
- await config.hooks?.onClear?.(event);
238
+ await config.hooks?.onClear?.(event, config);
251
239
  }
252
- function getEncryptKey(secret) {
253
- if (typeof secret === "string") {
254
- return secret;
255
- } else if (isSymmetricJWK(secret)) {
256
- return secret;
240
+ function getEncryptKey(key) {
241
+ if (!key) {
242
+ throw new Error("Session: JWE key is required.");
243
+ }
244
+ let _key;
245
+ if (typeof key === "string") {
246
+ _key = key;
247
+ } else if (isSymmetricJWK(key) || isPrivateJWK(key)) {
248
+ _key = key;
249
+ } else if ("publicKey" in key && isPublicJWK(key.publicKey)) {
250
+ _key = key.publicKey;
251
+ } else if ("privateKey" in key && isPrivateJWK(key.privateKey)) {
252
+ _key = key.privateKey;
253
+ }
254
+ if (!_key) {
255
+ throw new Error(
256
+ "Session: Invalid JWE key. It must be a password string or valid JWK.",
257
+ { cause: key }
258
+ );
257
259
  }
258
- return secret.publicKey || secret.privateKey;
260
+ return _key;
259
261
  }
260
- function getDecryptKey(secret) {
261
- if (typeof secret === "string") {
262
- return secret;
263
- } else if ("privateKey" in secret) {
264
- return secret.privateKey;
262
+ function getDecryptKey(key) {
263
+ if (!key) {
264
+ throw new Error("Session: JWE key is required.");
265
+ }
266
+ let _key = void 0;
267
+ if (typeof key === "string") {
268
+ _key = key;
269
+ } else if (isSymmetricJWK(key)) {
270
+ _key = key;
271
+ } else if ("privateKey" in key) {
272
+ _key = key.privateKey;
273
+ }
274
+ if (!_key) {
275
+ throw new Error(
276
+ "Session: Invalid JWE key. It must be a password string or a valid private JWK.",
277
+ { cause: key }
278
+ );
265
279
  }
266
- return secret;
280
+ return _key;
267
281
  }
268
282
 
269
283
  /**
270
284
  * This is a fork of h3 library's session utility functions.
271
- * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/test/session.test.ts
285
+ * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
272
286
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
273
287
  */
274
288
  const kGetSessionPromise = Symbol("h3_jws_getSession");
@@ -318,22 +332,15 @@ async function getJWSSession(event, config) {
318
332
  }
319
333
  const existingSession = event.context.sessions[sessionName];
320
334
  if (existingSession) {
321
- if (existingSession.expiresAt === void 0) {
322
- const session2 = existingSession[kGetSessionPromise] || existingSession;
323
- await config.hooks?.onRead?.(await session2, event);
324
- return session2;
325
- } else {
326
- if (existingSession.expiresAt < Date.now() && isEvent(event)) {
327
- await config.hooks?.onExpire?.(event, void 0);
328
- return clearJWSSession(event, config).then(
329
- () => getJWSSession(event, config)
330
- );
331
- } else {
332
- const session2 = existingSession[kGetSessionPromise] || existingSession;
333
- await config.hooks?.onRead?.(await session2, event);
334
- return session2;
335
- }
335
+ const session2 = existingSession[kGetSessionPromise] ? await existingSession[kGetSessionPromise] : existingSession;
336
+ if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && isEvent(event)) {
337
+ await config.hooks?.onExpire?.(event, void 0, config);
338
+ return clearJWSSession(event, config).then(
339
+ () => getJWSSession(event, config)
340
+ );
336
341
  }
342
+ await config.hooks?.onRead?.(session2, event, config);
343
+ return session2;
337
344
  }
338
345
  const session = {
339
346
  id: "",
@@ -358,14 +365,11 @@ async function getJWSSession(event, config) {
358
365
  }
359
366
  if (token) {
360
367
  const promise = verifyJWSSession(event, config, token).catch(async (error_) => {
361
- if (error_ instanceof Error) {
362
- const message = error_.message;
363
- if (message.includes("Token has expired") || message.includes("Token is too old")) {
364
- await config.hooks?.onExpire?.(event, error_);
365
- return void 0;
366
- }
368
+ if (error_ instanceof Error && (error_.message.includes("Token has expired") || error_.message.includes("Token is too old"))) {
369
+ await config.hooks?.onExpire?.(event, error_, config);
370
+ return void 0;
367
371
  }
368
- await config.hooks?.onError?.(event, error_);
372
+ await config.hooks?.onError?.(event, error_, config);
369
373
  return void 0;
370
374
  }).then((unsealed) => {
371
375
  if (unsealed) {
@@ -383,13 +387,12 @@ async function getJWSSession(event, config) {
383
387
  "Cannot initialize a new session outside main handler. Use `useJWSSession(event)` properly."
384
388
  );
385
389
  }
386
- session.id = config.generateId?.() ?? (config.crypto || globalThis.crypto).randomUUID();
387
- session.createdAt = config.jws?.signOptions?.currentDate === void 0 ? Date.now() : config.jws.signOptions.currentDate.getTime();
390
+ session.id = config.generateId?.() ?? crypto.randomUUID();
391
+ session.createdAt = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
388
392
  session.expiresAt = config.maxAge ? session.createdAt + config.maxAge * 1e3 : void 0;
389
- session.data = /* @__PURE__ */ Object.create(null);
390
393
  await updateJWSSession(event, config);
391
394
  }
392
- await config.hooks?.onRead?.(session, event);
395
+ await config.hooks?.onRead?.(session, event, config);
393
396
  return session;
394
397
  }
395
398
  function _getReqHeader(event, name) {
@@ -411,7 +414,7 @@ async function updateJWSSession(event, config, update) {
411
414
  }
412
415
  if (update) {
413
416
  Object.assign(session.data, update);
414
- await config.hooks?.onUpdate?.(session, event);
417
+ await config.hooks?.onUpdate?.(session, event, config);
415
418
  }
416
419
  if (config.cookie !== false) {
417
420
  const token = await signJWSSession(event, config);
@@ -425,9 +428,6 @@ async function updateJWSSession(event, config, update) {
425
428
  }
426
429
  async function signJWSSession(event, config) {
427
430
  const key = getSignKey(config.key);
428
- if (isAsymmetricJWK(key) && !isPrivateJWK(key)) {
429
- throw new Error("Session: JWS key cannot be a public asymmetric JWK.");
430
- }
431
431
  const sessionName = config.name || DEFAULT_NAME;
432
432
  const session = event.context.sessions?.[sessionName] || await getJWSSession(event, config);
433
433
  const iatSeconds = Math.floor(session.createdAt / 1e3);
@@ -440,11 +440,19 @@ async function signJWSSession(event, config) {
440
440
  if (expSeconds) {
441
441
  payload.exp = expSeconds;
442
442
  }
443
+ let typ = void 0;
444
+ if (config.jws?.signOptions?.protectedHeader?.typ && typeof config.jws.signOptions.protectedHeader.typ === "string" && config.jws.signOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
445
+ typ = config.jws.signOptions.protectedHeader.typ;
446
+ }
443
447
  const token = await sign(payload, key, {
444
448
  ...config.jws?.signOptions,
449
+ expiresIn: void 0,
450
+ // controlled via 'exp' claim
445
451
  protectedHeader: {
446
452
  ...config.jws?.signOptions?.protectedHeader,
447
- typ: "JWT"
453
+ kid: key.kid,
454
+ typ: typ || "JWT",
455
+ cty: "application/json"
448
456
  }
449
457
  });
450
458
  return token;
@@ -452,8 +460,9 @@ async function signJWSSession(event, config) {
452
460
  async function verifyJWSSession(_event, config, token) {
453
461
  const alg = config.jws?.signOptions?.alg;
454
462
  const jwk = getVerifyKey(config.key);
455
- if (isAsymmetricJWK(jwk) && isPrivateJWK(jwk)) {
456
- throw new Error("Session: JWS key cannot be a private asymmetric JWK.");
463
+ let typ = void 0;
464
+ if (config.jws?.signOptions?.protectedHeader?.typ && typeof config.jws.signOptions.protectedHeader.typ === "string" && config.jws.signOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
465
+ typ = config.jws.signOptions.protectedHeader.typ;
457
466
  }
458
467
  const { payload } = await verify(token, jwk, {
459
468
  ...config.jws?.verifyOptions,
@@ -464,7 +473,7 @@ async function verifyJWSSession(_event, config, token) {
464
473
  "jti",
465
474
  "iat"
466
475
  ],
467
- typ: "JWT",
476
+ typ: typ || "JWT",
468
477
  algorithms: alg ? [alg] : void 0,
469
478
  forceUint8Array: false,
470
479
  validateJWT: true
@@ -492,19 +501,48 @@ async function clearJWSSession(event, config) {
492
501
  expires: /* @__PURE__ */ new Date(0),
493
502
  maxAge: void 0
494
503
  });
495
- await config.hooks?.onClear?.(event);
504
+ await config.hooks?.onClear?.(event, config);
496
505
  }
497
506
  function getSignKey(key) {
498
- if ("privateKey" in key) {
499
- return key.privateKey;
507
+ if (!key) {
508
+ throw new Error("Session: JWS key is required.");
509
+ }
510
+ let _key = void 0;
511
+ if (isSymmetricJWK(key)) {
512
+ _key = key;
513
+ } else if ("privateKey" in key && isPrivateJWK(key.privateKey)) {
514
+ _key = key.privateKey;
500
515
  }
501
- return key;
516
+ if (!_key) {
517
+ throw new Error(
518
+ "Session: Invalid JWS key. It must be a symmetric JWK or a private JWK.",
519
+ { cause: key }
520
+ );
521
+ }
522
+ return _key;
502
523
  }
503
524
  function getVerifyKey(key) {
504
- if ("publicKey" in key) {
505
- return Array.isArray(key.publicKey) ? { keys: key.publicKey } : key.publicKey;
525
+ if (!key) {
526
+ throw new Error("Session: JWS key is required.");
527
+ }
528
+ let _key = void 0;
529
+ if (isSymmetricJWK(key)) {
530
+ _key = key;
531
+ } else if ("publicKey" in key && isPublicJWK(key.publicKey)) {
532
+ _key = key.publicKey;
533
+ } else if ("publicKey" in key && Array.isArray(key.publicKey)) {
534
+ const keys = key.publicKey.filter((k) => isPublicJWK(k));
535
+ if (keys && keys.length > 0) {
536
+ _key = { keys };
537
+ }
538
+ }
539
+ if (!_key) {
540
+ throw new Error(
541
+ "Session: Invalid JWS key. It must be a symmetric JWK or a public JWK/set.",
542
+ { cause: key }
543
+ );
506
544
  }
507
- return key;
545
+ return _key;
508
546
  }
509
547
 
510
548
  export { clearJWESession, clearJWSSession, getJWESession, getJWSSession, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { i as utils } from './shared/unjwt.DCiTNyCM.mjs';
2
- export { j as jwe } from './shared/unjwt.CXl9FD-V.mjs';
3
- export { j as jwk } from './shared/unjwt.Vg02PZWw.mjs';
4
- export { j as jws } from './shared/unjwt.DmRAjMp8.mjs';
1
+ export { i as utils } from './shared/unjwt.C86hA0o-.mjs';
2
+ export { j as jwe } from './shared/unjwt.CiBEuvtQ.mjs';
3
+ export { j as jwk } from './shared/unjwt.epPK1KFr.mjs';
4
+ export { j as jws } from './shared/unjwt.D-FATaw1.mjs';
package/dist/jwe.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import './shared/unjwt.Vg02PZWw.mjs';
2
- import './shared/unjwt.DCiTNyCM.mjs';
3
- export { d as decrypt, e as encrypt } from './shared/unjwt.CXl9FD-V.mjs';
1
+ import './shared/unjwt.epPK1KFr.mjs';
2
+ import './shared/unjwt.C86hA0o-.mjs';
3
+ export { d as decrypt, e as encrypt } from './shared/unjwt.CiBEuvtQ.mjs';
package/dist/jwk.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import './shared/unjwt.DCiTNyCM.mjs';
2
- export { k as deriveJWKFromPassword, m as deriveKeyFromPassword, h as exportJWKToPEM, n as exportKey, c as generateJWK, l as generateKey, b as getJWKFromSet, f as importJWKFromPEM, i as importKey, u as unwrapKey, w as wrapKey } from './shared/unjwt.Vg02PZWw.mjs';
1
+ import './shared/unjwt.C86hA0o-.mjs';
2
+ export { k as deriveJWKFromPassword, m as deriveKeyFromPassword, h as exportJWKToPEM, n as exportKey, c as generateJWK, l as generateKey, b as getJWKFromSet, f as importJWKFromPEM, i as importKey, u as unwrapKey, w as wrapKey } from './shared/unjwt.epPK1KFr.mjs';
package/dist/jws.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import './shared/unjwt.Vg02PZWw.mjs';
2
- import './shared/unjwt.DCiTNyCM.mjs';
3
- export { s as sign, v as verify } from './shared/unjwt.DmRAjMp8.mjs';
1
+ import './shared/unjwt.epPK1KFr.mjs';
2
+ import './shared/unjwt.C86hA0o-.mjs';
3
+ export { s as sign, v as verify } from './shared/unjwt.D-FATaw1.mjs';
@@ -435,4 +435,4 @@ const index = {
435
435
  validateJwtClaims: validateJwtClaims
436
436
  };
437
437
 
438
- export { maybeArray as A, isPublicJWK as B, isJWTContent as C, decodeMaybeJWTString as D, computeExpiresInSeconds as E, computeMaxTokenAgeSeconds as F, isJWK as a, applyTypCtyDefaults as b, computeJwtTimeClaims as c, base64UrlEncode as d, base64UrlDecode as e, decodePayloadFromBytes as f, getPlaintextBytes as g, validateJwtClaims as h, index as i, isCryptoKeyPair as j, isCryptoKey as k, textDecoder as l, isJWKSet as m, decodePayloadFromB64UrlSegment as n, validateCriticalHeadersJWS as o, isSymmetricJWK as p, isPrivateJWK as q, randomBytes as r, sanitizeObject as s, textEncoder as t, isAsymmetricJWK as u, validateCriticalHeadersJWE as v, concatUint8Arrays as w, base64Decode as x, base64Encode as y, assertCryptoKey as z };
438
+ export { isAsymmetricJWK as A, maybeArray as B, isJWTContent as C, decodeMaybeJWTString as D, computeExpiresInSeconds as E, computeMaxTokenAgeSeconds as F, isJWK as a, applyTypCtyDefaults as b, computeJwtTimeClaims as c, base64UrlEncode as d, base64UrlDecode as e, decodePayloadFromBytes as f, getPlaintextBytes as g, validateJwtClaims as h, index as i, isCryptoKeyPair as j, isCryptoKey as k, textDecoder as l, isJWKSet as m, decodePayloadFromB64UrlSegment as n, validateCriticalHeadersJWS as o, isSymmetricJWK as p, isPrivateJWK as q, randomBytes as r, sanitizeObject as s, textEncoder as t, isPublicJWK as u, validateCriticalHeadersJWE as v, concatUint8Arrays as w, base64Decode as x, base64Encode as y, assertCryptoKey as z };
@@ -1,5 +1,5 @@
1
- import { i as importKey, e as encryptKey, g as generateIV, a as encrypt$1, u as unwrapKey, d as decrypt$1 } from './unjwt.Vg02PZWw.mjs';
2
- import { r as randomBytes, a as isJWK, s as sanitizeObject, b as applyTypCtyDefaults, c as computeJwtTimeClaims, g as getPlaintextBytes, d as base64UrlEncode, t as textEncoder, e as base64UrlDecode, f as decodePayloadFromBytes, v as validateCriticalHeadersJWE, h as validateJwtClaims, j as isCryptoKeyPair, k as isCryptoKey } from './unjwt.DCiTNyCM.mjs';
1
+ import { i as importKey, e as encryptKey, g as generateIV, a as encrypt$1, u as unwrapKey, d as decrypt$1 } from './unjwt.epPK1KFr.mjs';
2
+ import { r as randomBytes, a as isJWK, s as sanitizeObject, b as applyTypCtyDefaults, c as computeJwtTimeClaims, g as getPlaintextBytes, d as base64UrlEncode, t as textEncoder, e as base64UrlDecode, f as decodePayloadFromBytes, v as validateCriticalHeadersJWE, h as validateJwtClaims, j as isCryptoKeyPair, k as isCryptoKey } from './unjwt.C86hA0o-.mjs';
3
3
 
4
4
  async function encrypt(payload, key, options = {}) {
5
5
  const {
@@ -1,5 +1,5 @@
1
- import { i as importKey, s as sign$1, b as getJWKFromSet, v as verify$1 } from './unjwt.Vg02PZWw.mjs';
2
- import { s as sanitizeObject, a as isJWK, b as applyTypCtyDefaults, c as computeJwtTimeClaims, d as base64UrlEncode, t as textEncoder, l as textDecoder, e as base64UrlDecode, m as isJWKSet, n as decodePayloadFromB64UrlSegment, o as validateCriticalHeadersJWS, h as validateJwtClaims } from './unjwt.DCiTNyCM.mjs';
1
+ import { i as importKey, s as sign$1, b as getJWKFromSet, v as verify$1 } from './unjwt.epPK1KFr.mjs';
2
+ import { s as sanitizeObject, a as isJWK, b as applyTypCtyDefaults, c as computeJwtTimeClaims, d as base64UrlEncode, t as textEncoder, l as textDecoder, e as base64UrlDecode, m as isJWKSet, n as decodePayloadFromB64UrlSegment, o as validateCriticalHeadersJWS, h as validateJwtClaims } from './unjwt.C86hA0o-.mjs';
3
3
 
4
4
  async function sign(payload, key, options = {}) {
5
5
  const { protectedHeader: additionalProtectedHeader } = options;
@@ -1,4 +1,4 @@
1
- import { k as isCryptoKey, w as concatUint8Arrays, d as base64UrlEncode, x as base64Decode, y as base64Encode, t as textEncoder, s as sanitizeObject, z as assertCryptoKey, a as isJWK, e as base64UrlDecode, u as isAsymmetricJWK, r as randomBytes, m as isJWKSet } from './unjwt.DCiTNyCM.mjs';
1
+ import { k as isCryptoKey, w as concatUint8Arrays, d as base64UrlEncode, x as base64Decode, y as base64Encode, t as textEncoder, s as sanitizeObject, z as assertCryptoKey, a as isJWK, e as base64UrlDecode, A as isAsymmetricJWK, r as randomBytes, m as isJWKSet } from './unjwt.C86hA0o-.mjs';
2
2
 
3
3
  /**
4
4
  * This is a fork of Jose library's utility functions.
@@ -1482,7 +1482,10 @@ async function generateJWK(alg, jwkParams, options = {}) {
1482
1482
  } = options;
1483
1483
  return generateKey(alg, {
1484
1484
  ...opts,
1485
- toJWK: jwkParams || true
1485
+ toJWK: {
1486
+ kid: typeof jwkParams?.kid === "string" ? jwkParams.kid : crypto.randomUUID(),
1487
+ ...jwkParams
1488
+ }
1486
1489
  });
1487
1490
  }
1488
1491
  async function deriveKeyFromPassword(password, alg, options) {
package/dist/utils.mjs CHANGED
@@ -1 +1 @@
1
- export { b as applyTypCtyDefaults, z as assertCryptoKey, x as base64Decode, y as base64Encode, e as base64UrlDecode, d as base64UrlEncode, E as computeExpiresInSeconds, c as computeJwtTimeClaims, F as computeMaxTokenAgeSeconds, w as concatUint8Arrays, D as decodeMaybeJWTString, n as decodePayloadFromB64UrlSegment, f as decodePayloadFromBytes, g as getPlaintextBytes, u as isAsymmetricJWK, k as isCryptoKey, j as isCryptoKeyPair, a as isJWK, m as isJWKSet, C as isJWTContent, q as isPrivateJWK, B as isPublicJWK, p as isSymmetricJWK, A as maybeArray, r as randomBytes, s as sanitizeObject, l as textDecoder, t as textEncoder, v as validateCriticalHeadersJWE, o as validateCriticalHeadersJWS, h as validateJwtClaims } from './shared/unjwt.DCiTNyCM.mjs';
1
+ export { b as applyTypCtyDefaults, z as assertCryptoKey, x as base64Decode, y as base64Encode, e as base64UrlDecode, d as base64UrlEncode, E as computeExpiresInSeconds, c as computeJwtTimeClaims, F as computeMaxTokenAgeSeconds, w as concatUint8Arrays, D as decodeMaybeJWTString, n as decodePayloadFromB64UrlSegment, f as decodePayloadFromBytes, g as getPlaintextBytes, A as isAsymmetricJWK, k as isCryptoKey, j as isCryptoKeyPair, a as isJWK, m as isJWKSet, C as isJWTContent, q as isPrivateJWK, u as isPublicJWK, p as isSymmetricJWK, B as maybeArray, r as randomBytes, s as sanitizeObject, l as textDecoder, t as textEncoder, v as validateCriticalHeadersJWE, o as validateCriticalHeadersJWS, h as validateJwtClaims } from './shared/unjwt.C86hA0o-.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unjwt",
3
- "version": "0.5.22",
3
+ "version": "0.5.23",
4
4
  "description": "Low-level JWT utilities",
5
5
  "repository": "sandros94/unjwt",
6
6
  "license": "MIT",
@@ -44,7 +44,7 @@
44
44
  ],
45
45
  "scripts": {
46
46
  "build": "unbuild",
47
- "dev": "vitest dev",
47
+ "dev": "bun --watch ./playground/main.ts",
48
48
  "lint": "eslint . && prettier -c .",
49
49
  "lint:fix": "automd && eslint . --fix && prettier -w .",
50
50
  "prepack": "pnpm build",