unjwt 0.5.36 → 0.5.38

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 CHANGED
@@ -605,6 +605,9 @@ console.log(rsaPublicSpki);
605
605
 
606
606
  ### Adapters
607
607
 
608
+ > [!WARNING]
609
+ > While these adapters try to be compatible with h3's `useSession` API, the key difference is that new sessions are not automatically created when calling `useJWESession` or `useJWSSession`, marking their `id` as `undefined` until you explicitly call `session.update()`. This is to comply with various specs that do integrate JWT one (such as OAuth) where sessions are only created upon valid operations (like user authorization).
610
+
608
611
  #### H3 v1 (Nuxt v4, Nitro v2)
609
612
 
610
613
  The `h3v1` adapter bundles session helpers that store data inside signed or encrypted JWTs.
@@ -18,7 +18,9 @@ interface SessionManager<T extends Record<string, any> = SessionClaims, ConfigMa
18
18
  readonly expiresAt: ConfigMaxAge extends ExpiresIn ? number : "exp" extends keyof T ? T["exp"] : number | undefined;
19
19
  readonly data: SessionData<T>;
20
20
  readonly token: string | undefined;
21
- update: (update: SessionUpdate<T>) => Promise<SessionManager<T, ConfigMaxAge>>;
21
+ update: (update: SessionUpdate<T>) => Promise<SessionManager<T, ConfigMaxAge> & {
22
+ readonly id: string;
23
+ }>;
22
24
  clear: () => Promise<SessionManager<T, ConfigMaxAge>>;
23
25
  }
24
26
 
@@ -30,7 +32,7 @@ interface SessionManager<T extends Record<string, any> = SessionClaims, ConfigMa
30
32
 
31
33
  declare const kGetSessionPromise$1: unique symbol;
32
34
  interface SessionJWE<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
33
- id: string;
35
+ id: string | undefined;
34
36
  createdAt: number;
35
37
  expiresAt: MaxAge extends ExpiresIn ? number : T["exp"];
36
38
  data: SessionData<T>;
@@ -151,7 +153,7 @@ declare function clearJWESession<T extends Record<string, any> = SessionClaims,
151
153
 
152
154
  declare const kGetSessionPromise: unique symbol;
153
155
  interface SessionJWS<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
154
- id: string;
156
+ id: string | undefined;
155
157
  createdAt: number;
156
158
  expiresAt: MaxAge extends ExpiresIn ? number : T["exp"];
157
159
  data: SessionData<T>;
@@ -80,10 +80,12 @@ async function getJWESession(event, config) {
80
80
  });
81
81
  return session2;
82
82
  }
83
+ const now = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
84
+ const createdAt = now - now % 1e3;
83
85
  const session = {
84
- id: "",
85
- createdAt: 0,
86
- expiresAt: void 0,
86
+ id: void 0,
87
+ createdAt,
88
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
87
89
  data: /* @__PURE__ */ Object.create(null)
88
90
  };
89
91
  event.context.sessions[sessionName] = session;
@@ -114,17 +116,6 @@ async function getJWESession(event, config) {
114
116
  event.context.sessions[sessionName][kGetSessionPromise$1] = promise;
115
117
  await promise;
116
118
  }
117
- if (!session.id) {
118
- if (!isEvent(event)) {
119
- throw new Error(
120
- "Cannot initialize a new session. Use `useSession(event)` within the main handler."
121
- );
122
- }
123
- session.id = config.generateId?.() ?? crypto.randomUUID();
124
- session.createdAt = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
125
- session.expiresAt = config.maxAge === void 0 ? void 0 : session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3;
126
- await updateJWESession(event, config);
127
- }
128
119
  await config.hooks?.onRead?.({
129
120
  event,
130
121
  session,
@@ -183,6 +174,11 @@ function _getResHeader$1(event, name) {
183
174
  }
184
175
  }
185
176
  async function updateJWESession(event, config, update) {
177
+ if (!isEvent(event)) {
178
+ throw new Error(
179
+ "Cannot update a new session. Use `useSession(event)` within the main handler."
180
+ );
181
+ }
186
182
  const sessionName = config.name || DEFAULT_NAME$1;
187
183
  const session = event.context.sessions?.[sessionName] || await getJWESession(event, config);
188
184
  if (typeof update === "function") {
@@ -198,6 +194,13 @@ async function updateJWESession(event, config, update) {
198
194
  config
199
195
  });
200
196
  }
197
+ const now = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
198
+ const createdAt = now - now % 1e3;
199
+ Object.assign(session, {
200
+ id: config.generateId?.() || crypto.randomUUID(),
201
+ createdAt,
202
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
203
+ });
201
204
  if (config.cookie !== false) {
202
205
  const sealed = await sealJWESession(event, config);
203
206
  setCookie(event, sessionName, sealed, {
@@ -215,8 +218,8 @@ async function sealJWESession(event, config) {
215
218
  const key = getEncryptKey(config.key || config.secret);
216
219
  const sessionName = config.name || DEFAULT_NAME$1;
217
220
  const session = event.context.sessions?.[sessionName] || await getJWESession(event, config);
218
- const iat = Math.floor(Date.now() / 1e3);
219
- const exp = config.maxAge === void 0 ? void 0 : iat + computeExpiresInSeconds(config.maxAge);
221
+ const iat = Math.floor(session.createdAt / 1e3);
222
+ const exp = session.expiresAt ? Math.floor(session.expiresAt / 1e3) : void 0;
220
223
  const payload = {
221
224
  ...session.data,
222
225
  jti: session.id,
@@ -429,10 +432,12 @@ async function getJWSSession(event, config) {
429
432
  });
430
433
  return session2;
431
434
  }
435
+ const now = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
436
+ const createdAt = now - now % 1e3;
432
437
  const session = {
433
- id: "",
434
- createdAt: 0,
435
- expiresAt: void 0,
438
+ id: void 0,
439
+ createdAt,
440
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
436
441
  data: /* @__PURE__ */ Object.create(null)
437
442
  };
438
443
  event.context.sessions[sessionName] = session;
@@ -463,17 +468,6 @@ async function getJWSSession(event, config) {
463
468
  session[kGetSessionPromise] = promise;
464
469
  await promise;
465
470
  }
466
- if (!session.id) {
467
- if (!isEvent(event)) {
468
- throw new Error(
469
- "Cannot initialize a new session outside main handler. Use `useJWSSession(event)` properly."
470
- );
471
- }
472
- session.id = config.generateId?.() ?? crypto.randomUUID();
473
- session.createdAt = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
474
- session.expiresAt = config.maxAge === void 0 ? void 0 : session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3;
475
- await updateJWSSession(event, config);
476
- }
477
471
  await config.hooks?.onRead?.({
478
472
  event,
479
473
  session,
@@ -532,6 +526,11 @@ function _getResHeader(event, name) {
532
526
  }
533
527
  }
534
528
  async function updateJWSSession(event, config, update) {
529
+ if (!isEvent(event)) {
530
+ throw new Error(
531
+ "Cannot update a new session. Use `useSession(event)` within the main handler."
532
+ );
533
+ }
535
534
  const sessionName = config.name || DEFAULT_NAME;
536
535
  const session = event.context.sessions?.[sessionName] || await getJWSSession(event, config);
537
536
  if (typeof update === "function") {
@@ -547,6 +546,13 @@ async function updateJWSSession(event, config, update) {
547
546
  config
548
547
  });
549
548
  }
549
+ const now = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
550
+ const createdAt = now - now % 1e3;
551
+ Object.assign(session, {
552
+ id: config.generateId?.() || crypto.randomUUID(),
553
+ createdAt,
554
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
555
+ });
550
556
  if (config.cookie !== false) {
551
557
  const token = await signJWSSession(event, config);
552
558
  setCookie(event, sessionName, token, {
@@ -563,8 +569,8 @@ async function signJWSSession(event, config) {
563
569
  const key = getSignKey(config.key);
564
570
  const sessionName = config.name || DEFAULT_NAME;
565
571
  const session = event.context.sessions?.[sessionName] || await getJWSSession(event, config);
566
- const iat = Math.floor(Date.now() / 1e3);
567
- const exp = config.maxAge === void 0 ? void 0 : iat + computeExpiresInSeconds(config.maxAge);
572
+ const iat = Math.floor(session.createdAt / 1e3);
573
+ const exp = session.expiresAt ? Math.floor(session.expiresAt / 1e3) : void 0;
568
574
  const payload = {
569
575
  ...session.data,
570
576
  jti: session.id,
@@ -24,7 +24,7 @@ interface SessionManager<T extends Record<string, any> = SessionClaims, ConfigMa
24
24
 
25
25
  declare const kGetSessionPromise$1: unique symbol;
26
26
  interface SessionJWE<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
27
- id: string;
27
+ id: string | undefined;
28
28
  createdAt: number;
29
29
  expiresAt: MaxAge extends ExpiresIn ? number : T["exp"];
30
30
  data: SessionData<T>;
@@ -116,7 +116,7 @@ declare function clearJWESession<T extends Record<string, any> = SessionClaims,
116
116
 
117
117
  declare const kGetSessionPromise: unique symbol;
118
118
  interface SessionJWS<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
119
- id: string;
119
+ id: string | undefined;
120
120
  createdAt: number;
121
121
  expiresAt: MaxAge extends ExpiresIn ? number : T["exp"];
122
122
  data: SessionData<T>;
@@ -70,10 +70,12 @@ async function getJWESession(event, config) {
70
70
  });
71
71
  return session2;
72
72
  }
73
+ const now = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
74
+ const createdAt = now - now % 1e3;
73
75
  const session = {
74
- id: "",
75
- createdAt: 0,
76
- expiresAt: void 0,
76
+ id: void 0,
77
+ createdAt,
78
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
77
79
  data: new NullProtoObj()
78
80
  };
79
81
  context.sessions[sessionName] = session;
@@ -107,12 +109,6 @@ async function getJWESession(event, config) {
107
109
  session[kGetSessionPromise$1] = promise;
108
110
  await promise;
109
111
  }
110
- if (!session.id) {
111
- session.id = config.generateId?.() ?? crypto.randomUUID();
112
- session.createdAt = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
113
- session.expiresAt = config.maxAge === void 0 ? void 0 : session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3;
114
- await updateJWESession(event, config);
115
- }
116
112
  await config.hooks?.onRead?.({
117
113
  event,
118
114
  session,
@@ -158,6 +154,13 @@ async function updateJWESession(event, config, update) {
158
154
  config
159
155
  });
160
156
  }
157
+ const now = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
158
+ const createdAt = now - now % 1e3;
159
+ Object.assign(session, {
160
+ id: config.generateId?.() || crypto.randomUUID(),
161
+ createdAt,
162
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
163
+ });
161
164
  if (config.cookie !== false && hasWritableResponse$1(event)) {
162
165
  const sealed = await sealJWESession(event, config);
163
166
  setChunkedCookie(event, sessionName, sealed, {
@@ -175,8 +178,8 @@ async function sealJWESession(event, config) {
175
178
  const sessionName = config.name || DEFAULT_NAME$1;
176
179
  const context = getEventContext(event);
177
180
  const session = context.sessions?.[sessionName] || await getJWESession(event, config);
178
- const iat = Math.floor(Date.now() / 1e3);
179
- const exp = config.maxAge === void 0 ? void 0 : iat + computeExpiresInSeconds(config.maxAge);
181
+ const iat = Math.floor(session.createdAt / 1e3);
182
+ const exp = session.expiresAt ? Math.floor(session.expiresAt / 1e3) : void 0;
180
183
  const payload = {
181
184
  ...session.data,
182
185
  jti: session.id,
@@ -386,10 +389,12 @@ async function getJWSSession(event, config) {
386
389
  });
387
390
  return session2;
388
391
  }
392
+ const now = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
393
+ const createdAt = now - now % 1e3;
389
394
  const session = {
390
- id: "",
391
- createdAt: 0,
392
- expiresAt: void 0,
395
+ id: void 0,
396
+ createdAt,
397
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
393
398
  data: new NullProtoObj()
394
399
  };
395
400
  context.sessions[sessionName] = session;
@@ -420,12 +425,6 @@ async function getJWSSession(event, config) {
420
425
  session[kGetSessionPromise] = promise;
421
426
  await promise;
422
427
  }
423
- if (!session.id) {
424
- session.id = config.generateId?.() ?? crypto.randomUUID();
425
- session.createdAt = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
426
- session.expiresAt = config.maxAge === void 0 ? void 0 : session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3;
427
- await updateJWSSession(event, config);
428
- }
429
428
  await config.hooks?.onRead?.({
430
429
  event,
431
430
  session,
@@ -471,6 +470,13 @@ async function updateJWSSession(event, config, update) {
471
470
  config
472
471
  });
473
472
  }
473
+ const now = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
474
+ const createdAt = now - now % 1e3;
475
+ Object.assign(session, {
476
+ id: config.generateId?.() || crypto.randomUUID(),
477
+ createdAt,
478
+ expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
479
+ });
474
480
  if (config.cookie !== false && hasWritableResponse(event)) {
475
481
  const token = await signJWSSession(event, config);
476
482
  setChunkedCookie(event, sessionName, token, {
@@ -488,8 +494,8 @@ async function signJWSSession(event, config) {
488
494
  const sessionName = config.name || DEFAULT_NAME;
489
495
  const context = getEventContext(event);
490
496
  const session = context.sessions?.[sessionName] || await getJWSSession(event, config);
491
- const iat = Math.floor(Date.now() / 1e3);
492
- const exp = config.maxAge === void 0 ? void 0 : iat + computeExpiresInSeconds(config.maxAge);
497
+ const iat = Math.floor(session.createdAt / 1e3);
498
+ const exp = session.expiresAt ? Math.floor(session.expiresAt / 1e3) : void 0;
493
499
  const payload = {
494
500
  ...session.data,
495
501
  jti: session.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unjwt",
3
- "version": "0.5.36",
3
+ "version": "0.5.38",
4
4
  "description": "Low-level JWT utilities",
5
5
  "repository": "sandros94/unjwt",
6
6
  "license": "MIT",