unjwt 0.5.40 → 0.6.1
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 +147 -6
- package/dist/_chunks/_crypto.mjs +1014 -0
- package/dist/_chunks/error.d.mts +67 -0
- package/dist/_chunks/index.d.mts +149 -45
- package/dist/_chunks/jwk.d.mts +154 -57
- package/dist/_chunks/jws.mjs +729 -683
- package/dist/_chunks/utils.mjs +74 -70
- package/dist/{_chunks/jws.d.mts → adapters/h3v1/index.d.mts} +98 -58
- package/dist/{_chunks/jws2.mjs → adapters/h3v1/index.mjs} +198 -85
- package/dist/adapters/h3v2/index.d.mts +213 -0
- package/dist/adapters/{h3v2.mjs → h3v2/index.mjs} +195 -89
- package/dist/core/_crypto/index.d.mts +71 -0
- package/dist/core/_crypto/index.mjs +2 -0
- package/dist/core/jwe.d.mts +40 -0
- package/dist/{_chunks → core}/jwe.mjs +61 -32
- package/dist/core/jwk.d.mts +231 -0
- package/dist/core/jwk.mjs +686 -0
- package/dist/core/jws.d.mts +31 -0
- package/dist/core/jws.mjs +104 -0
- package/dist/{_chunks/index2.d.mts → core/utils/index.d.mts} +13 -12
- package/dist/core/utils/index.mjs +2 -0
- package/dist/index.d.mts +7 -6
- package/dist/index.mjs +5 -5
- package/package.json +48 -40
- package/dist/_chunks/chunk.mjs +0 -13
- package/dist/_chunks/jwe.d.mts +0 -43
- package/dist/_chunks/jwk.mjs +0 -1592
- package/dist/adapters/h3.d.mts +0 -3
- package/dist/adapters/h3.mjs +0 -3
- package/dist/adapters/h3v1.d.mts +0 -3
- package/dist/adapters/h3v1.mjs +0 -3
- package/dist/adapters/h3v2.d.mts +0 -183
- package/dist/jwe.d.mts +0 -3
- package/dist/jwe.mjs +0 -2
- package/dist/jwk.d.mts +0 -3
- package/dist/jwk.mjs +0 -2
- package/dist/jws.d.mts +0 -3
- package/dist/jws.mjs +0 -2
- package/dist/utils.d.mts +0 -3
- package/dist/utils.mjs +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as isSymmetricJWK, f as computeExpiresInSeconds, i as encrypt, l as isPrivateJWK, n as verify, r as decrypt, t as sign, u as isPublicJWK } from "
|
|
1
|
+
import { a as deriveJWKFromPassword, c as importFromPEM, d as isSymmetricJWK, f as computeExpiresInSeconds, i as encrypt, l as isPrivateJWK, m as isJWTError, n as verify, o as exportToPEM, p as JWTError, r as decrypt, s as generateJWK, t as sign, u as isPublicJWK } from "../../_chunks/jws.mjs";
|
|
2
2
|
import { isEvent, setCookie } from "h3";
|
|
3
3
|
import { parse } from "cookie-es";
|
|
4
4
|
//#region src/adapters/h3v1/session/jwe.ts
|
|
@@ -29,15 +29,13 @@ async function useJWESession(event, config) {
|
|
|
29
29
|
return event.context.sessions?.[sessionName]?.data || {};
|
|
30
30
|
},
|
|
31
31
|
get token() {
|
|
32
|
-
return getJWESessionToken(event, config);
|
|
32
|
+
return (event.context.sessions?.[sessionName])?.token ?? getJWESessionToken(event, config);
|
|
33
33
|
},
|
|
34
34
|
update: async (update) => {
|
|
35
|
-
if (!isEvent(event)) throw new Error("[h3] Cannot update read-only session.");
|
|
36
35
|
await updateJWESession(event, config, update);
|
|
37
36
|
return sessionManager;
|
|
38
37
|
},
|
|
39
38
|
clear: async () => {
|
|
40
|
-
if (!isEvent(event)) throw new Error("[h3] Cannot clear read-only session.");
|
|
41
39
|
await clearJWESession(event, config);
|
|
42
40
|
return sessionManager;
|
|
43
41
|
}
|
|
@@ -58,17 +56,44 @@ async function getJWESession(event, config) {
|
|
|
58
56
|
* unless we have a read-only event in which case we just return it as it was valid at the time of reading
|
|
59
57
|
* the cookie/header (like in a websocket upgrade)
|
|
60
58
|
*/
|
|
61
|
-
if (session.expiresAt !== void 0 && session.expiresAt < Date.now()
|
|
59
|
+
if (session.expiresAt !== void 0 && session.expiresAt < Date.now()) {
|
|
62
60
|
await config.hooks?.onExpire?.({
|
|
61
|
+
session: {
|
|
62
|
+
id: session.id,
|
|
63
|
+
createdAt: session.createdAt,
|
|
64
|
+
expiresAt: session.expiresAt,
|
|
65
|
+
token: session.token
|
|
66
|
+
},
|
|
63
67
|
event,
|
|
64
|
-
error:
|
|
68
|
+
error: new JWTError(`JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${(/* @__PURE__ */ new Date(session.expiresAt * 1e3)).toISOString()})`, "ERR_JWT_EXPIRED", {
|
|
69
|
+
jti: session.id,
|
|
70
|
+
exp: session.expiresAt / 1e3
|
|
71
|
+
}),
|
|
65
72
|
config
|
|
66
73
|
});
|
|
67
|
-
|
|
74
|
+
delete event.context.sessions[sessionName];
|
|
75
|
+
if (config.cookie !== false) if (isEvent(event)) setCookie(event, sessionName, "", {
|
|
76
|
+
...DEFAULT_COOKIE$1,
|
|
77
|
+
...config.cookie,
|
|
78
|
+
expires: /* @__PURE__ */ new Date(0),
|
|
79
|
+
maxAge: void 0
|
|
80
|
+
});
|
|
81
|
+
else console.warn("[unjwt/h3] Session expired but cookie cannot be cleared on a read-only event.");
|
|
82
|
+
const freshNow = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
|
|
83
|
+
const freshCreatedAt = freshNow - freshNow % 1e3;
|
|
84
|
+
const freshSession = {
|
|
85
|
+
id: void 0,
|
|
86
|
+
createdAt: freshCreatedAt,
|
|
87
|
+
expiresAt: config.maxAge === void 0 ? void 0 : freshCreatedAt + computeExpiresInSeconds(config.maxAge) * 1e3,
|
|
88
|
+
data: Object.create(null),
|
|
89
|
+
token: void 0
|
|
90
|
+
};
|
|
91
|
+
event.context.sessions[sessionName] = freshSession;
|
|
92
|
+
return freshSession;
|
|
68
93
|
}
|
|
69
|
-
await config.hooks?.onRead?.({
|
|
70
|
-
event,
|
|
94
|
+
if (session.id !== void 0 && session.token !== void 0) await config.hooks?.onRead?.({
|
|
71
95
|
session,
|
|
96
|
+
event,
|
|
72
97
|
config
|
|
73
98
|
});
|
|
74
99
|
return session;
|
|
@@ -79,23 +104,31 @@ async function getJWESession(event, config) {
|
|
|
79
104
|
id: void 0,
|
|
80
105
|
createdAt,
|
|
81
106
|
expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
|
|
82
|
-
data: Object.create(null)
|
|
107
|
+
data: Object.create(null),
|
|
108
|
+
token: void 0
|
|
83
109
|
};
|
|
84
110
|
event.context.sessions[sessionName] = session;
|
|
85
111
|
const token = getJWESessionToken(event, config);
|
|
112
|
+
let exclusiveHookFired = false;
|
|
86
113
|
if (token) {
|
|
114
|
+
session.token = token;
|
|
87
115
|
const promise = unsealJWESession(event, config, token).catch(async (error_) => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
116
|
+
exclusiveHookFired = true;
|
|
117
|
+
if (isJWTError(error_, "ERR_JWT_EXPIRED")) await config.hooks?.onExpire?.({
|
|
118
|
+
session: {
|
|
119
|
+
id: error_.cause.jti,
|
|
120
|
+
createdAt: error_.cause.iat ? error_.cause.iat * 1e3 : void 0,
|
|
121
|
+
expiresAt: error_.cause.exp ? error_.cause.exp * 1e3 : void 0,
|
|
122
|
+
token
|
|
123
|
+
},
|
|
124
|
+
error: error_,
|
|
97
125
|
event,
|
|
126
|
+
config
|
|
127
|
+
});
|
|
128
|
+
else await config.hooks?.onError?.({
|
|
129
|
+
session,
|
|
98
130
|
error: error_,
|
|
131
|
+
event,
|
|
99
132
|
config
|
|
100
133
|
});
|
|
101
134
|
}).then((unsealed) => {
|
|
@@ -106,9 +139,9 @@ async function getJWESession(event, config) {
|
|
|
106
139
|
event.context.sessions[sessionName][kGetSessionPromise$1] = promise;
|
|
107
140
|
await promise;
|
|
108
141
|
}
|
|
109
|
-
await config.hooks?.onRead?.({
|
|
110
|
-
event,
|
|
142
|
+
if (!exclusiveHookFired && session.id !== void 0 && session.token !== void 0) await config.hooks?.onRead?.({
|
|
111
143
|
session,
|
|
144
|
+
event,
|
|
112
145
|
config
|
|
113
146
|
});
|
|
114
147
|
return session;
|
|
@@ -147,23 +180,16 @@ function _getResHeader$1(event, name) {
|
|
|
147
180
|
* Update the session (optionally mutating the session data) and re-issue the JWE token.
|
|
148
181
|
*/
|
|
149
182
|
async function updateJWESession(event, config, update) {
|
|
150
|
-
|
|
183
|
+
const canWriteCookie = isEvent(event);
|
|
184
|
+
if (config.cookie !== false && !canWriteCookie) throw new Error("[unjwt/h3] Cannot update session on read-only event.");
|
|
151
185
|
const sessionName = config.name || DEFAULT_NAME$1;
|
|
152
186
|
const session = event.context.sessions?.[sessionName] || await getJWESession(event, config);
|
|
153
187
|
if (typeof update === "function") update = update(session.data);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
Object.assign(session.data, update);
|
|
160
|
-
await config.hooks?.onUpdate?.({
|
|
161
|
-
session,
|
|
162
|
-
oldSession,
|
|
163
|
-
event,
|
|
164
|
-
config
|
|
165
|
-
});
|
|
166
|
-
}
|
|
188
|
+
const oldSession = {
|
|
189
|
+
...session,
|
|
190
|
+
data: { ...session.data }
|
|
191
|
+
};
|
|
192
|
+
if (update) Object.assign(session.data, update);
|
|
167
193
|
const now = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
|
|
168
194
|
const createdAt = now - now % 1e3;
|
|
169
195
|
Object.assign(session, {
|
|
@@ -171,11 +197,36 @@ async function updateJWESession(event, config, update) {
|
|
|
171
197
|
createdAt,
|
|
172
198
|
expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
|
|
173
199
|
});
|
|
174
|
-
|
|
200
|
+
let sealed;
|
|
201
|
+
try {
|
|
202
|
+
sealed = await sealJWESession(event, config);
|
|
203
|
+
} catch (error_) {
|
|
204
|
+
Object.assign(session, {
|
|
205
|
+
id: oldSession.id,
|
|
206
|
+
createdAt: oldSession.createdAt,
|
|
207
|
+
expiresAt: oldSession.expiresAt
|
|
208
|
+
});
|
|
209
|
+
session.token = oldSession.token;
|
|
210
|
+
await config.hooks?.onError?.({
|
|
211
|
+
session,
|
|
212
|
+
event,
|
|
213
|
+
error: error_,
|
|
214
|
+
config
|
|
215
|
+
});
|
|
216
|
+
throw error_;
|
|
217
|
+
}
|
|
218
|
+
session.token = sealed;
|
|
219
|
+
if (config.cookie !== false && canWriteCookie) setCookie(event, sessionName, sealed, {
|
|
175
220
|
...DEFAULT_COOKIE$1,
|
|
176
221
|
...config.cookie,
|
|
177
222
|
expires: config.maxAge === void 0 ? void 0 : new Date(session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3)
|
|
178
223
|
});
|
|
224
|
+
await config.hooks?.onUpdate?.({
|
|
225
|
+
session,
|
|
226
|
+
oldSession,
|
|
227
|
+
event,
|
|
228
|
+
config
|
|
229
|
+
});
|
|
179
230
|
return session;
|
|
180
231
|
}
|
|
181
232
|
/**
|
|
@@ -189,7 +240,7 @@ async function updateJWESession(event, config, update) {
|
|
|
189
240
|
* }
|
|
190
241
|
*/
|
|
191
242
|
async function sealJWESession(event, config) {
|
|
192
|
-
const key = getEncryptKey(config.key
|
|
243
|
+
const key = getEncryptKey(config.key);
|
|
193
244
|
const sessionName = config.name || DEFAULT_NAME$1;
|
|
194
245
|
const session = event.context.sessions?.[sessionName] || await getJWESession(event, config);
|
|
195
246
|
const iat = Math.floor(session.createdAt / 1e3);
|
|
@@ -221,7 +272,7 @@ async function unsealJWESession(event, config, sealed) {
|
|
|
221
272
|
header,
|
|
222
273
|
event,
|
|
223
274
|
config
|
|
224
|
-
}) : getDecryptKey(config.key
|
|
275
|
+
}) : getDecryptKey(config.key);
|
|
225
276
|
const alg = config.jwe?.encryptOptions?.alg;
|
|
226
277
|
const enc = config.jwe?.encryptOptions?.enc;
|
|
227
278
|
let typ = void 0;
|
|
@@ -240,13 +291,11 @@ async function unsealJWESession(event, config, sealed) {
|
|
|
240
291
|
unwrappedKeyAlgorithm: void 0,
|
|
241
292
|
keyUsage: void 0,
|
|
242
293
|
forceUint8Array: false,
|
|
243
|
-
|
|
294
|
+
validateClaims: true
|
|
244
295
|
}).catch((error_) => {
|
|
245
|
-
if (error_
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
throw new Error(error_);
|
|
296
|
+
if (isJWTError(error_, "ERR_JWT_EXPIRED")) throw error_;
|
|
297
|
+
const message = error_ instanceof Error ? error_.message : String(error_);
|
|
298
|
+
throw new Error(`Invalid session token: ${message}`);
|
|
250
299
|
});
|
|
251
300
|
const { jti, iat, exp, ...data } = payload;
|
|
252
301
|
return {
|
|
@@ -260,18 +309,24 @@ async function unsealJWESession(event, config, sealed) {
|
|
|
260
309
|
* Clear the session (delete from context and drop cookie).
|
|
261
310
|
*/
|
|
262
311
|
async function clearJWESession(event, config) {
|
|
312
|
+
const canWriteCookie = isEvent(event);
|
|
313
|
+
if (config.cookie !== false && !canWriteCookie) throw new Error("[unjwt/h3] Cannot clear session on read-only event.");
|
|
263
314
|
const sessionName = config.name || DEFAULT_NAME$1;
|
|
264
315
|
let session = event.context.sessions?.[sessionName];
|
|
265
316
|
if (session && session[kGetSessionPromise$1]) session = await session[kGetSessionPromise$1];
|
|
317
|
+
const oldSession = session ? {
|
|
318
|
+
...session,
|
|
319
|
+
data: { ...session.data }
|
|
320
|
+
} : void 0;
|
|
266
321
|
if (event.context.sessions?.[sessionName]) delete event.context.sessions[sessionName];
|
|
267
|
-
setCookie(event, sessionName, "", {
|
|
322
|
+
if (config.cookie !== false && canWriteCookie) setCookie(event, sessionName, "", {
|
|
268
323
|
...DEFAULT_COOKIE$1,
|
|
269
324
|
...config.cookie,
|
|
270
325
|
expires: /* @__PURE__ */ new Date(0),
|
|
271
326
|
maxAge: void 0
|
|
272
327
|
});
|
|
273
328
|
await config.hooks?.onClear?.({
|
|
274
|
-
|
|
329
|
+
oldSession,
|
|
275
330
|
event,
|
|
276
331
|
config
|
|
277
332
|
});
|
|
@@ -330,15 +385,13 @@ async function useJWSSession(event, config) {
|
|
|
330
385
|
return event.context.sessions?.[sessionName]?.data || {};
|
|
331
386
|
},
|
|
332
387
|
get token() {
|
|
333
|
-
return getJWSSessionToken(event, config);
|
|
388
|
+
return (event.context.sessions?.[sessionName])?.token ?? getJWSSessionToken(event, config);
|
|
334
389
|
},
|
|
335
390
|
update: async (update) => {
|
|
336
|
-
if (!isEvent(event)) throw new Error("[h3] Cannot update read-only session.");
|
|
337
391
|
await updateJWSSession(event, config, update);
|
|
338
392
|
return sessionManager;
|
|
339
393
|
},
|
|
340
394
|
clear: async () => {
|
|
341
|
-
if (!isEvent(event)) throw new Error("[h3] Cannot clear read-only session.");
|
|
342
395
|
await clearJWSSession(event, config);
|
|
343
396
|
return sessionManager;
|
|
344
397
|
}
|
|
@@ -359,17 +412,44 @@ async function getJWSSession(event, config) {
|
|
|
359
412
|
* unless we have a read-only event in which case we just return it as it was valid at the time of reading
|
|
360
413
|
* the cookie/header (like in a websocket upgrade)
|
|
361
414
|
*/
|
|
362
|
-
if (session.expiresAt !== void 0 && session.expiresAt < Date.now()
|
|
415
|
+
if (session.expiresAt !== void 0 && session.expiresAt < Date.now()) {
|
|
363
416
|
await config.hooks?.onExpire?.({
|
|
417
|
+
session: {
|
|
418
|
+
id: session.id,
|
|
419
|
+
createdAt: session.createdAt,
|
|
420
|
+
expiresAt: session.expiresAt,
|
|
421
|
+
token: session.token
|
|
422
|
+
},
|
|
364
423
|
event,
|
|
365
|
-
error:
|
|
424
|
+
error: new JWTError(`JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${(/* @__PURE__ */ new Date(session.expiresAt * 1e3)).toISOString()})`, "ERR_JWT_EXPIRED", {
|
|
425
|
+
jti: session.id,
|
|
426
|
+
exp: session.expiresAt / 1e3
|
|
427
|
+
}),
|
|
366
428
|
config
|
|
367
429
|
});
|
|
368
|
-
|
|
430
|
+
delete event.context.sessions[sessionName];
|
|
431
|
+
if (config.cookie !== false) if (isEvent(event)) setCookie(event, sessionName, "", {
|
|
432
|
+
...DEFAULT_COOKIE,
|
|
433
|
+
...config.cookie,
|
|
434
|
+
expires: /* @__PURE__ */ new Date(0),
|
|
435
|
+
maxAge: void 0
|
|
436
|
+
});
|
|
437
|
+
else console.warn("[unjwt/h3] Session expired but cookie cannot be cleared on a read-only event.");
|
|
438
|
+
const freshNow = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
|
|
439
|
+
const freshCreatedAt = freshNow - freshNow % 1e3;
|
|
440
|
+
const freshSession = {
|
|
441
|
+
id: void 0,
|
|
442
|
+
createdAt: freshCreatedAt,
|
|
443
|
+
expiresAt: config.maxAge === void 0 ? void 0 : freshCreatedAt + computeExpiresInSeconds(config.maxAge) * 1e3,
|
|
444
|
+
data: Object.create(null),
|
|
445
|
+
token: void 0
|
|
446
|
+
};
|
|
447
|
+
event.context.sessions[sessionName] = freshSession;
|
|
448
|
+
return freshSession;
|
|
369
449
|
}
|
|
370
|
-
await config.hooks?.onRead?.({
|
|
371
|
-
event,
|
|
450
|
+
if (session.id !== void 0 && session.token !== void 0) await config.hooks?.onRead?.({
|
|
372
451
|
session,
|
|
452
|
+
event,
|
|
373
453
|
config
|
|
374
454
|
});
|
|
375
455
|
return session;
|
|
@@ -380,23 +460,31 @@ async function getJWSSession(event, config) {
|
|
|
380
460
|
id: void 0,
|
|
381
461
|
createdAt,
|
|
382
462
|
expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
|
|
383
|
-
data: Object.create(null)
|
|
463
|
+
data: Object.create(null),
|
|
464
|
+
token: void 0
|
|
384
465
|
};
|
|
385
466
|
event.context.sessions[sessionName] = session;
|
|
386
467
|
const token = getJWSSessionToken(event, config);
|
|
468
|
+
let exclusiveHookFired = false;
|
|
387
469
|
if (token) {
|
|
470
|
+
session.token = token;
|
|
388
471
|
const promise = verifyJWSSession(event, config, token).catch(async (error_) => {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
472
|
+
exclusiveHookFired = true;
|
|
473
|
+
if (isJWTError(error_, "ERR_JWT_EXPIRED")) await config.hooks?.onExpire?.({
|
|
474
|
+
session: {
|
|
475
|
+
id: error_.cause.jti,
|
|
476
|
+
createdAt: error_.cause.iat ? error_.cause.iat * 1e3 : void 0,
|
|
477
|
+
expiresAt: error_.cause.exp ? error_.cause.exp * 1e3 : void 0,
|
|
478
|
+
token
|
|
479
|
+
},
|
|
480
|
+
error: error_,
|
|
398
481
|
event,
|
|
482
|
+
config
|
|
483
|
+
});
|
|
484
|
+
else await config.hooks?.onError?.({
|
|
485
|
+
session,
|
|
399
486
|
error: error_,
|
|
487
|
+
event,
|
|
400
488
|
config
|
|
401
489
|
});
|
|
402
490
|
}).then((unsealed) => {
|
|
@@ -407,9 +495,9 @@ async function getJWSSession(event, config) {
|
|
|
407
495
|
session[kGetSessionPromise] = promise;
|
|
408
496
|
await promise;
|
|
409
497
|
}
|
|
410
|
-
await config.hooks?.onRead?.({
|
|
411
|
-
event,
|
|
498
|
+
if (!exclusiveHookFired && session.id !== void 0 && session.token !== void 0) await config.hooks?.onRead?.({
|
|
412
499
|
session,
|
|
500
|
+
event,
|
|
413
501
|
config
|
|
414
502
|
});
|
|
415
503
|
return session;
|
|
@@ -448,23 +536,16 @@ function _getResHeader(event, name) {
|
|
|
448
536
|
* Update session data (if provided) and reissue JWS.
|
|
449
537
|
*/
|
|
450
538
|
async function updateJWSSession(event, config, update) {
|
|
451
|
-
|
|
539
|
+
const canWriteCookie = isEvent(event);
|
|
540
|
+
if (config.cookie !== false && !canWriteCookie) throw new Error("[unjwt/h3] Cannot update session on read-only event.");
|
|
452
541
|
const sessionName = config.name || DEFAULT_NAME;
|
|
453
542
|
const session = event.context.sessions?.[sessionName] || await getJWSSession(event, config);
|
|
454
543
|
if (typeof update === "function") update = update(session.data);
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
Object.assign(session.data, update);
|
|
461
|
-
await config.hooks?.onUpdate?.({
|
|
462
|
-
session,
|
|
463
|
-
oldSession,
|
|
464
|
-
event,
|
|
465
|
-
config
|
|
466
|
-
});
|
|
467
|
-
}
|
|
544
|
+
const oldSession = {
|
|
545
|
+
...session,
|
|
546
|
+
data: { ...session.data }
|
|
547
|
+
};
|
|
548
|
+
if (update) Object.assign(session.data, update);
|
|
468
549
|
const now = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
|
|
469
550
|
const createdAt = now - now % 1e3;
|
|
470
551
|
Object.assign(session, {
|
|
@@ -472,11 +553,36 @@ async function updateJWSSession(event, config, update) {
|
|
|
472
553
|
createdAt,
|
|
473
554
|
expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
|
|
474
555
|
});
|
|
475
|
-
|
|
556
|
+
let token;
|
|
557
|
+
try {
|
|
558
|
+
token = await signJWSSession(event, config);
|
|
559
|
+
} catch (error_) {
|
|
560
|
+
Object.assign(session, {
|
|
561
|
+
id: oldSession.id,
|
|
562
|
+
createdAt: oldSession.createdAt,
|
|
563
|
+
expiresAt: oldSession.expiresAt
|
|
564
|
+
});
|
|
565
|
+
session.token = oldSession.token;
|
|
566
|
+
await config.hooks?.onError?.({
|
|
567
|
+
session,
|
|
568
|
+
event,
|
|
569
|
+
error: error_,
|
|
570
|
+
config
|
|
571
|
+
});
|
|
572
|
+
throw error_;
|
|
573
|
+
}
|
|
574
|
+
session.token = token;
|
|
575
|
+
if (config.cookie !== false && canWriteCookie) setCookie(event, sessionName, token, {
|
|
476
576
|
...DEFAULT_COOKIE,
|
|
477
577
|
...config.cookie,
|
|
478
578
|
expires: config.maxAge === void 0 ? void 0 : new Date(session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3)
|
|
479
579
|
});
|
|
580
|
+
await config.hooks?.onUpdate?.({
|
|
581
|
+
session,
|
|
582
|
+
oldSession,
|
|
583
|
+
event,
|
|
584
|
+
config
|
|
585
|
+
});
|
|
480
586
|
return session;
|
|
481
587
|
}
|
|
482
588
|
/**
|
|
@@ -536,8 +642,9 @@ async function verifyJWSSession(event, config, token) {
|
|
|
536
642
|
typ: typ || "JWT",
|
|
537
643
|
algorithms: alg ? [alg] : void 0,
|
|
538
644
|
forceUint8Array: false,
|
|
539
|
-
|
|
645
|
+
validateClaims: true
|
|
540
646
|
}).catch((error_) => {
|
|
647
|
+
if (isJWTError(error_, "ERR_JWT_EXPIRED")) throw error_;
|
|
541
648
|
const message = error_ instanceof Error ? error_.message : String(error_);
|
|
542
649
|
throw new Error(`Invalid session token: ${message}`);
|
|
543
650
|
});
|
|
@@ -553,18 +660,24 @@ async function verifyJWSSession(event, config, token) {
|
|
|
553
660
|
* Destroy the session (context + cookie).
|
|
554
661
|
*/
|
|
555
662
|
async function clearJWSSession(event, config) {
|
|
663
|
+
const canWriteCookie = isEvent(event);
|
|
664
|
+
if (config.cookie !== false && !canWriteCookie) throw new Error("[unjwt/h3] Cannot clear session on read-only event.");
|
|
556
665
|
const sessionName = config.name || DEFAULT_NAME;
|
|
557
666
|
let session = event.context.sessions?.[sessionName];
|
|
558
667
|
if (session && session[kGetSessionPromise]) session = await session[kGetSessionPromise];
|
|
668
|
+
const oldSession = session ? {
|
|
669
|
+
...session,
|
|
670
|
+
data: { ...session.data }
|
|
671
|
+
} : void 0;
|
|
559
672
|
if (event.context.sessions?.[sessionName]) delete event.context.sessions[sessionName];
|
|
560
|
-
setCookie(event, sessionName, "", {
|
|
673
|
+
if (config.cookie !== false && canWriteCookie) setCookie(event, sessionName, "", {
|
|
561
674
|
...DEFAULT_COOKIE,
|
|
562
675
|
...config.cookie,
|
|
563
676
|
expires: /* @__PURE__ */ new Date(0),
|
|
564
677
|
maxAge: void 0
|
|
565
678
|
});
|
|
566
679
|
await config.hooks?.onClear?.({
|
|
567
|
-
|
|
680
|
+
oldSession,
|
|
568
681
|
event,
|
|
569
682
|
config
|
|
570
683
|
});
|
|
@@ -595,4 +708,4 @@ function findSetCookie(setCookie, name) {
|
|
|
595
708
|
return match ? match[1] : void 0;
|
|
596
709
|
}
|
|
597
710
|
//#endregion
|
|
598
|
-
export {
|
|
711
|
+
export { clearJWESession, clearJWSSession, deriveJWKFromPassword, exportToPEM, generateJWK, getJWESession, getJWESessionToken, getJWSSession, importFromPEM, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession };
|