unjwt 0.5.38 → 0.5.40
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 +148 -670
- package/dist/_chunks/chunk.mjs +13 -0
- package/dist/_chunks/index.d.mts +558 -0
- package/dist/_chunks/index2.d.mts +108 -0
- package/dist/_chunks/jwe.d.mts +43 -0
- package/dist/_chunks/jwe.mjs +132 -0
- package/dist/_chunks/jwk.d.mts +611 -0
- package/dist/_chunks/jwk.mjs +1592 -0
- package/dist/_chunks/jws.d.mts +242 -0
- package/dist/_chunks/jws.mjs +2070 -0
- package/dist/_chunks/jws2.mjs +598 -0
- package/dist/_chunks/utils.mjs +375 -0
- package/dist/adapters/h3.d.mts +3 -267
- package/dist/adapters/h3.mjs +3 -704
- package/dist/adapters/h3v1.d.mts +3 -8
- package/dist/adapters/h3v1.mjs +3 -7
- package/dist/adapters/h3v2.d.mts +145 -147
- package/dist/adapters/h3v2.mjs +501 -594
- package/dist/index.d.mts +6 -8
- package/dist/index.mjs +5 -4
- package/dist/jwe.d.mts +3 -4
- package/dist/jwe.mjs +2 -3
- package/dist/jwk.d.mts +3 -2
- package/dist/jwk.mjs +2 -2
- package/dist/jws.d.mts +3 -3
- package/dist/jws.mjs +2 -3
- package/dist/utils.d.mts +3 -3
- package/dist/utils.mjs +2 -1
- package/package.json +33 -31
- package/dist/shared/unjwt.4JQCoID_.d.mts +0 -161
- package/dist/shared/unjwt.B-v62plj.mjs +0 -249
- package/dist/shared/unjwt.BCi3FEWr.d.mts +0 -328
- package/dist/shared/unjwt.BYDTEWa-.d.mts +0 -269
- package/dist/shared/unjwt.Be8NxwFK.mjs +0 -438
- package/dist/shared/unjwt.BqdNUKDr.d.mts +0 -64
- package/dist/shared/unjwt.CMNtw8ek.d.mts +0 -155
- package/dist/shared/unjwt.Cy2MlkUe.d.mts +0 -174
- package/dist/shared/unjwt.D0_ccT7g.d.mts +0 -166
- package/dist/shared/unjwt.DdLN9vwI.mjs +0 -163
- package/dist/shared/unjwt.Dpl__ZAR.mjs +0 -2121
- package/dist/shared/unjwt.JdKqVANs.d.mts +0 -5
package/dist/adapters/h3.mjs
CHANGED
|
@@ -1,704 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { e as encrypt, d as decrypt } from '../shared/unjwt.B-v62plj.mjs';
|
|
5
|
-
import { p as computeExpiresInSeconds, q as isSymmetricJWK, u as isPrivateJWK, w as isPublicJWK } from '../shared/unjwt.Be8NxwFK.mjs';
|
|
6
|
-
import { s as sign, v as verify } from '../shared/unjwt.DdLN9vwI.mjs';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* This is a fork of h3 library's session utility functions.
|
|
10
|
-
* @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
|
|
11
|
-
* @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
|
|
12
|
-
*/
|
|
13
|
-
const kGetSessionPromise$1 = Symbol("h3_jwe_getSession");
|
|
14
|
-
const DEFAULT_NAME$1 = "h3-jwe";
|
|
15
|
-
const DEFAULT_COOKIE$1 = {
|
|
16
|
-
path: "/",
|
|
17
|
-
secure: true,
|
|
18
|
-
httpOnly: true
|
|
19
|
-
};
|
|
20
|
-
async function useJWESession(event, config) {
|
|
21
|
-
const sessionName = config.name || DEFAULT_NAME$1;
|
|
22
|
-
await getJWESession(event, config);
|
|
23
|
-
const sessionManager = {
|
|
24
|
-
get id() {
|
|
25
|
-
return event.context.sessions?.[sessionName]?.id;
|
|
26
|
-
},
|
|
27
|
-
get createdAt() {
|
|
28
|
-
return event.context.sessions?.[sessionName]?.createdAt || Date.now();
|
|
29
|
-
},
|
|
30
|
-
get expiresAt() {
|
|
31
|
-
return event.context.sessions?.[sessionName]?.expiresAt;
|
|
32
|
-
},
|
|
33
|
-
get data() {
|
|
34
|
-
return event.context.sessions?.[sessionName]?.data || {};
|
|
35
|
-
},
|
|
36
|
-
get token() {
|
|
37
|
-
return getJWESessionToken(event, config);
|
|
38
|
-
},
|
|
39
|
-
update: async (update) => {
|
|
40
|
-
if (!isEvent(event)) {
|
|
41
|
-
throw new Error("[h3] Cannot update read-only session.");
|
|
42
|
-
}
|
|
43
|
-
await updateJWESession(event, config, update);
|
|
44
|
-
return sessionManager;
|
|
45
|
-
},
|
|
46
|
-
clear: () => {
|
|
47
|
-
if (!isEvent(event)) {
|
|
48
|
-
throw new Error("[h3] Cannot clear read-only session.");
|
|
49
|
-
}
|
|
50
|
-
clearJWESession(event, config);
|
|
51
|
-
return Promise.resolve(sessionManager);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
return sessionManager;
|
|
55
|
-
}
|
|
56
|
-
async function getJWESession(event, config) {
|
|
57
|
-
const sessionName = config.name || DEFAULT_NAME$1;
|
|
58
|
-
if (!event.context.sessions) {
|
|
59
|
-
event.context.sessions = /* @__PURE__ */ Object.create(null);
|
|
60
|
-
}
|
|
61
|
-
const existingSession = event.context.sessions[sessionName];
|
|
62
|
-
if (existingSession) {
|
|
63
|
-
const session2 = existingSession[kGetSessionPromise$1] ? await existingSession[kGetSessionPromise$1] : existingSession;
|
|
64
|
-
if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && isEvent(event)) {
|
|
65
|
-
await config.hooks?.onExpire?.({
|
|
66
|
-
event,
|
|
67
|
-
error: new Error(
|
|
68
|
-
`JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${new Date(session2.expiresAt * 1e3).toISOString()})`
|
|
69
|
-
),
|
|
70
|
-
config
|
|
71
|
-
});
|
|
72
|
-
return clearJWESession(event, config).then(
|
|
73
|
-
() => getJWESession(event, config)
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
await config.hooks?.onRead?.({
|
|
77
|
-
event,
|
|
78
|
-
session: session2,
|
|
79
|
-
config
|
|
80
|
-
});
|
|
81
|
-
return session2;
|
|
82
|
-
}
|
|
83
|
-
const now = config.jwe?.encryptOptions?.currentDate?.getTime() ?? Date.now();
|
|
84
|
-
const createdAt = now - now % 1e3;
|
|
85
|
-
const session = {
|
|
86
|
-
id: void 0,
|
|
87
|
-
createdAt,
|
|
88
|
-
expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
|
|
89
|
-
data: /* @__PURE__ */ Object.create(null)
|
|
90
|
-
};
|
|
91
|
-
event.context.sessions[sessionName] = session;
|
|
92
|
-
const token = getJWESessionToken(event, config);
|
|
93
|
-
if (token) {
|
|
94
|
-
const promise = unsealJWESession(event, config, token).catch(async (error_) => {
|
|
95
|
-
if (error_ instanceof Error && (error_.message.includes("Token has expired") || error_.message.includes("Token is too old"))) {
|
|
96
|
-
await config.hooks?.onExpire?.({
|
|
97
|
-
event,
|
|
98
|
-
error: error_,
|
|
99
|
-
config
|
|
100
|
-
});
|
|
101
|
-
return void 0;
|
|
102
|
-
}
|
|
103
|
-
await config.hooks?.onError?.({
|
|
104
|
-
event,
|
|
105
|
-
error: error_,
|
|
106
|
-
config
|
|
107
|
-
});
|
|
108
|
-
return void 0;
|
|
109
|
-
}).then((unsealed) => {
|
|
110
|
-
if (unsealed) {
|
|
111
|
-
Object.assign(session, unsealed);
|
|
112
|
-
}
|
|
113
|
-
delete event.context.sessions[sessionName][kGetSessionPromise$1];
|
|
114
|
-
return session;
|
|
115
|
-
});
|
|
116
|
-
event.context.sessions[sessionName][kGetSessionPromise$1] = promise;
|
|
117
|
-
await promise;
|
|
118
|
-
}
|
|
119
|
-
await config.hooks?.onRead?.({
|
|
120
|
-
event,
|
|
121
|
-
session,
|
|
122
|
-
config
|
|
123
|
-
});
|
|
124
|
-
return session;
|
|
125
|
-
}
|
|
126
|
-
function getJWESessionToken(event, config) {
|
|
127
|
-
const sessionName = config.name || DEFAULT_NAME$1;
|
|
128
|
-
let token;
|
|
129
|
-
if (config.sessionHeader !== false) {
|
|
130
|
-
const headerName = typeof config.sessionHeader === "string" ? config.sessionHeader.toLowerCase() : `x-${sessionName.toLowerCase()}-session`;
|
|
131
|
-
const headerValue = _getReqHeader$1(event, headerName);
|
|
132
|
-
if (typeof headerValue === "string") {
|
|
133
|
-
token = headerValue.startsWith("Bearer ") ? headerValue.slice(7).trim() : headerValue;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (config.cookie !== false) {
|
|
137
|
-
const setCookie2 = _getResHeader$1(event, "set-cookie");
|
|
138
|
-
if (typeof setCookie2 === "string") {
|
|
139
|
-
token = findSetCookie$1(setCookie2, sessionName);
|
|
140
|
-
} else if (Array.isArray(setCookie2)) {
|
|
141
|
-
for (const sc of setCookie2) {
|
|
142
|
-
token = findSetCookie$1(sc, sessionName);
|
|
143
|
-
if (token) {
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (!token) {
|
|
150
|
-
const cookieHeader = _getReqHeader$1(event, "cookie");
|
|
151
|
-
if (cookieHeader) {
|
|
152
|
-
token = parse(String(cookieHeader))[sessionName];
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return token;
|
|
156
|
-
}
|
|
157
|
-
function _getReqHeader$1(event, name) {
|
|
158
|
-
if (event.node) {
|
|
159
|
-
return event.node?.req.headers[name];
|
|
160
|
-
}
|
|
161
|
-
if (event.request) {
|
|
162
|
-
return event.request.headers?.get(name);
|
|
163
|
-
}
|
|
164
|
-
if (event.headers) {
|
|
165
|
-
return event.headers.get(name);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
function _getResHeader$1(event, name) {
|
|
169
|
-
if (event.node) {
|
|
170
|
-
return event.node?.res.getHeader(name);
|
|
171
|
-
}
|
|
172
|
-
if (event.response) {
|
|
173
|
-
return event.response.headers?.get(name);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
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
|
-
}
|
|
182
|
-
const sessionName = config.name || DEFAULT_NAME$1;
|
|
183
|
-
const session = event.context.sessions?.[sessionName] || await getJWESession(event, config);
|
|
184
|
-
if (typeof update === "function") {
|
|
185
|
-
update = update(session.data);
|
|
186
|
-
}
|
|
187
|
-
if (update) {
|
|
188
|
-
const oldSession = { ...session, data: { ...session.data } };
|
|
189
|
-
Object.assign(session.data, update);
|
|
190
|
-
await config.hooks?.onUpdate?.({
|
|
191
|
-
session,
|
|
192
|
-
oldSession,
|
|
193
|
-
event,
|
|
194
|
-
config
|
|
195
|
-
});
|
|
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
|
-
});
|
|
204
|
-
if (config.cookie !== false) {
|
|
205
|
-
const sealed = await sealJWESession(event, config);
|
|
206
|
-
setCookie(event, sessionName, sealed, {
|
|
207
|
-
...DEFAULT_COOKIE$1,
|
|
208
|
-
...config.cookie,
|
|
209
|
-
expires: config.maxAge === void 0 ? void 0 : new Date(
|
|
210
|
-
// createdAt is ms, maxAge is seconds
|
|
211
|
-
session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
|
|
212
|
-
)
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
return session;
|
|
216
|
-
}
|
|
217
|
-
async function sealJWESession(event, config) {
|
|
218
|
-
const key = getEncryptKey(config.key || config.secret);
|
|
219
|
-
const sessionName = config.name || DEFAULT_NAME$1;
|
|
220
|
-
const session = event.context.sessions?.[sessionName] || await getJWESession(event, config);
|
|
221
|
-
const iat = Math.floor(session.createdAt / 1e3);
|
|
222
|
-
const exp = session.expiresAt ? Math.floor(session.expiresAt / 1e3) : void 0;
|
|
223
|
-
const payload = {
|
|
224
|
-
...session.data,
|
|
225
|
-
jti: session.id,
|
|
226
|
-
iat
|
|
227
|
-
};
|
|
228
|
-
if (exp) {
|
|
229
|
-
payload.exp = exp;
|
|
230
|
-
}
|
|
231
|
-
let typ = void 0;
|
|
232
|
-
if (config.jwe?.encryptOptions?.protectedHeader?.typ && typeof config.jwe.encryptOptions.protectedHeader.typ === "string" && config.jwe.encryptOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
|
|
233
|
-
typ = config.jwe.encryptOptions.protectedHeader.typ;
|
|
234
|
-
}
|
|
235
|
-
const token = await encrypt(payload, key, {
|
|
236
|
-
...config.jwe?.encryptOptions,
|
|
237
|
-
expiresIn: void 0,
|
|
238
|
-
// controlled via 'exp' claim
|
|
239
|
-
protectedHeader: {
|
|
240
|
-
...config.jwe?.encryptOptions?.protectedHeader,
|
|
241
|
-
kid: typeof key === "string" ? void 0 : key.kid,
|
|
242
|
-
typ: typ || "JWT",
|
|
243
|
-
cty: "application/json"
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
return token;
|
|
247
|
-
}
|
|
248
|
-
async function unsealJWESession(event, config, sealed) {
|
|
249
|
-
const key = config.hooks?.onUnsealKeyLookup ? (header) => config.hooks.onUnsealKeyLookup({
|
|
250
|
-
header,
|
|
251
|
-
event,
|
|
252
|
-
config
|
|
253
|
-
}) : getDecryptKey(config.key || config.secret);
|
|
254
|
-
const alg = config.jwe?.encryptOptions?.alg;
|
|
255
|
-
const enc = config.jwe?.encryptOptions?.enc;
|
|
256
|
-
if (config.jwe?.encryptOptions?.protectedHeader?.typ && typeof config.jwe.encryptOptions.protectedHeader.typ === "string" && config.jwe.encryptOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
|
|
257
|
-
config.jwe.encryptOptions.protectedHeader.typ;
|
|
258
|
-
}
|
|
259
|
-
const { payload } = await decrypt(sealed, key, {
|
|
260
|
-
...config.jwe?.decryptOptions,
|
|
261
|
-
requiredClaims: [
|
|
262
|
-
.../* @__PURE__ */ new Set([
|
|
263
|
-
...config.jwe?.decryptOptions?.requiredClaims || [],
|
|
264
|
-
"jti",
|
|
265
|
-
"iat"
|
|
266
|
-
])
|
|
267
|
-
],
|
|
268
|
-
maxTokenAge: config.maxAge,
|
|
269
|
-
algorithms: alg ? [alg] : void 0,
|
|
270
|
-
encryptionAlgorithms: enc ? [enc] : void 0,
|
|
271
|
-
unwrappedKeyAlgorithm: void 0,
|
|
272
|
-
keyUsage: void 0,
|
|
273
|
-
forceUint8Array: false,
|
|
274
|
-
validateJWT: true
|
|
275
|
-
}).catch((error_) => {
|
|
276
|
-
if (error_ instanceof Error) {
|
|
277
|
-
const message = error_.message;
|
|
278
|
-
throw new Error(`Invalid session token: ${message}`);
|
|
279
|
-
}
|
|
280
|
-
throw new Error(error_);
|
|
281
|
-
});
|
|
282
|
-
const { jti, iat, exp, ...data } = payload;
|
|
283
|
-
return {
|
|
284
|
-
id: jti,
|
|
285
|
-
createdAt: iat * 1e3,
|
|
286
|
-
// Convert back to ms
|
|
287
|
-
expiresAt: exp ? exp * 1e3 : void 0,
|
|
288
|
-
data: data && typeof data === "object" ? data : /* @__PURE__ */ Object.create(null)
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
async function clearJWESession(event, config) {
|
|
292
|
-
const sessionName = config.name || DEFAULT_NAME$1;
|
|
293
|
-
let session = event.context.sessions?.[sessionName];
|
|
294
|
-
if (session && session[kGetSessionPromise$1]) {
|
|
295
|
-
session = await session[kGetSessionPromise$1];
|
|
296
|
-
}
|
|
297
|
-
if (event.context.sessions?.[sessionName]) {
|
|
298
|
-
delete event.context.sessions[sessionName];
|
|
299
|
-
}
|
|
300
|
-
setCookie(event, sessionName, "", {
|
|
301
|
-
...DEFAULT_COOKIE$1,
|
|
302
|
-
...config.cookie,
|
|
303
|
-
expires: /* @__PURE__ */ new Date(0),
|
|
304
|
-
maxAge: void 0
|
|
305
|
-
});
|
|
306
|
-
await config.hooks?.onClear?.({
|
|
307
|
-
session,
|
|
308
|
-
event,
|
|
309
|
-
config
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
function getEncryptKey(key) {
|
|
313
|
-
if (!key) {
|
|
314
|
-
throw new Error("Session: JWE key is required.");
|
|
315
|
-
}
|
|
316
|
-
let _key;
|
|
317
|
-
if (typeof key === "string") {
|
|
318
|
-
_key = key;
|
|
319
|
-
} else if (isSymmetricJWK(key) || isPrivateJWK(key)) {
|
|
320
|
-
_key = key;
|
|
321
|
-
} else if ("publicKey" in key && isPublicJWK(key.publicKey)) {
|
|
322
|
-
_key = key.publicKey;
|
|
323
|
-
} else if ("privateKey" in key && isPrivateJWK(key.privateKey)) {
|
|
324
|
-
_key = key.privateKey;
|
|
325
|
-
}
|
|
326
|
-
if (!_key) {
|
|
327
|
-
throw new Error(
|
|
328
|
-
"Session: Invalid JWE key. It must be a password string or valid JWK.",
|
|
329
|
-
{ cause: key }
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
return _key;
|
|
333
|
-
}
|
|
334
|
-
function getDecryptKey(key) {
|
|
335
|
-
if (!key) {
|
|
336
|
-
throw new Error("Session: JWE key is required.");
|
|
337
|
-
}
|
|
338
|
-
let _key = void 0;
|
|
339
|
-
if (typeof key === "string") {
|
|
340
|
-
_key = key;
|
|
341
|
-
} else if (isSymmetricJWK(key)) {
|
|
342
|
-
_key = key;
|
|
343
|
-
} else if ("privateKey" in key) {
|
|
344
|
-
_key = key.privateKey;
|
|
345
|
-
}
|
|
346
|
-
if (!_key) {
|
|
347
|
-
throw new Error(
|
|
348
|
-
"Session: Invalid JWE key. It must be a password string or a valid private JWK.",
|
|
349
|
-
{ cause: key }
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
return _key;
|
|
353
|
-
}
|
|
354
|
-
function findSetCookie$1(setCookie2, name) {
|
|
355
|
-
const regex = new RegExp(`(?:^|,\\s*)${name}=([^;]+)`);
|
|
356
|
-
const match = setCookie2.match(regex);
|
|
357
|
-
return match ? match[1] : void 0;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* This is a fork of h3 library's session utility functions.
|
|
362
|
-
* @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
|
|
363
|
-
* @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
|
|
364
|
-
*/
|
|
365
|
-
const kGetSessionPromise = Symbol("h3_jws_getSession");
|
|
366
|
-
const DEFAULT_NAME = "h3-jws";
|
|
367
|
-
const DEFAULT_COOKIE = {
|
|
368
|
-
path: "/",
|
|
369
|
-
secure: true,
|
|
370
|
-
httpOnly: false
|
|
371
|
-
};
|
|
372
|
-
async function useJWSSession(event, config) {
|
|
373
|
-
const sessionName = config.name || DEFAULT_NAME;
|
|
374
|
-
await getJWSSession(event, config);
|
|
375
|
-
const sessionManager = {
|
|
376
|
-
get id() {
|
|
377
|
-
return event.context.sessions?.[sessionName]?.id;
|
|
378
|
-
},
|
|
379
|
-
get createdAt() {
|
|
380
|
-
return event.context.sessions?.[sessionName]?.createdAt || Date.now();
|
|
381
|
-
},
|
|
382
|
-
get expiresAt() {
|
|
383
|
-
return event.context.sessions?.[sessionName]?.expiresAt;
|
|
384
|
-
},
|
|
385
|
-
get data() {
|
|
386
|
-
return event.context.sessions?.[sessionName]?.data || {};
|
|
387
|
-
},
|
|
388
|
-
get token() {
|
|
389
|
-
return getJWSSessionToken(event, config);
|
|
390
|
-
},
|
|
391
|
-
update: async (update) => {
|
|
392
|
-
if (!isEvent(event)) {
|
|
393
|
-
throw new Error("[h3] Cannot update read-only session.");
|
|
394
|
-
}
|
|
395
|
-
await updateJWSSession(event, config, update);
|
|
396
|
-
return sessionManager;
|
|
397
|
-
},
|
|
398
|
-
clear: () => {
|
|
399
|
-
if (!isEvent(event)) {
|
|
400
|
-
throw new Error("[h3] Cannot clear read-only session.");
|
|
401
|
-
}
|
|
402
|
-
clearJWSSession(event, config);
|
|
403
|
-
return Promise.resolve(sessionManager);
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
return sessionManager;
|
|
407
|
-
}
|
|
408
|
-
async function getJWSSession(event, config) {
|
|
409
|
-
const sessionName = config.name || DEFAULT_NAME;
|
|
410
|
-
if (!event.context.sessions) {
|
|
411
|
-
event.context.sessions = /* @__PURE__ */ Object.create(null);
|
|
412
|
-
}
|
|
413
|
-
const existingSession = event.context.sessions[sessionName];
|
|
414
|
-
if (existingSession) {
|
|
415
|
-
const session2 = existingSession[kGetSessionPromise] ? await existingSession[kGetSessionPromise] : existingSession;
|
|
416
|
-
if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && isEvent(event)) {
|
|
417
|
-
await config.hooks?.onExpire?.({
|
|
418
|
-
event,
|
|
419
|
-
error: new Error(
|
|
420
|
-
`JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${new Date(session2.expiresAt * 1e3).toISOString()})`
|
|
421
|
-
),
|
|
422
|
-
config
|
|
423
|
-
});
|
|
424
|
-
return clearJWSSession(event, config).then(
|
|
425
|
-
() => getJWSSession(event, config)
|
|
426
|
-
);
|
|
427
|
-
}
|
|
428
|
-
await config.hooks?.onRead?.({
|
|
429
|
-
event,
|
|
430
|
-
session: session2,
|
|
431
|
-
config
|
|
432
|
-
});
|
|
433
|
-
return session2;
|
|
434
|
-
}
|
|
435
|
-
const now = config.jws?.signOptions?.currentDate?.getTime() ?? Date.now();
|
|
436
|
-
const createdAt = now - now % 1e3;
|
|
437
|
-
const session = {
|
|
438
|
-
id: void 0,
|
|
439
|
-
createdAt,
|
|
440
|
-
expiresAt: config.maxAge === void 0 ? void 0 : createdAt + computeExpiresInSeconds(config.maxAge) * 1e3,
|
|
441
|
-
data: /* @__PURE__ */ Object.create(null)
|
|
442
|
-
};
|
|
443
|
-
event.context.sessions[sessionName] = session;
|
|
444
|
-
const token = getJWSSessionToken(event, config);
|
|
445
|
-
if (token) {
|
|
446
|
-
const promise = verifyJWSSession(event, config, token).catch(async (error_) => {
|
|
447
|
-
if (error_ instanceof Error && (error_.message.includes("Token has expired") || error_.message.includes("Token is too old"))) {
|
|
448
|
-
await config.hooks?.onExpire?.({
|
|
449
|
-
event,
|
|
450
|
-
error: error_,
|
|
451
|
-
config
|
|
452
|
-
});
|
|
453
|
-
return void 0;
|
|
454
|
-
}
|
|
455
|
-
await config.hooks?.onError?.({
|
|
456
|
-
event,
|
|
457
|
-
error: error_,
|
|
458
|
-
config
|
|
459
|
-
});
|
|
460
|
-
return void 0;
|
|
461
|
-
}).then((unsealed) => {
|
|
462
|
-
if (unsealed) {
|
|
463
|
-
Object.assign(session, unsealed);
|
|
464
|
-
}
|
|
465
|
-
delete event.context.sessions[sessionName][kGetSessionPromise];
|
|
466
|
-
return session;
|
|
467
|
-
});
|
|
468
|
-
session[kGetSessionPromise] = promise;
|
|
469
|
-
await promise;
|
|
470
|
-
}
|
|
471
|
-
await config.hooks?.onRead?.({
|
|
472
|
-
event,
|
|
473
|
-
session,
|
|
474
|
-
config
|
|
475
|
-
});
|
|
476
|
-
return session;
|
|
477
|
-
}
|
|
478
|
-
function getJWSSessionToken(event, config) {
|
|
479
|
-
const sessionName = config.name || DEFAULT_NAME;
|
|
480
|
-
let token;
|
|
481
|
-
if (config.sessionHeader !== false) {
|
|
482
|
-
const headerName = typeof config.sessionHeader === "string" ? config.sessionHeader.toLowerCase() : `x-${sessionName.toLowerCase()}-session`;
|
|
483
|
-
const headerValue = _getReqHeader(event, headerName);
|
|
484
|
-
if (typeof headerValue === "string") {
|
|
485
|
-
token = headerValue.startsWith("Bearer ") ? headerValue.slice(7).trim() : headerValue;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
if (config.cookie !== false) {
|
|
489
|
-
const setCookie2 = _getResHeader(event, "set-cookie");
|
|
490
|
-
if (typeof setCookie2 === "string") {
|
|
491
|
-
token = findSetCookie(setCookie2, sessionName);
|
|
492
|
-
} else if (Array.isArray(setCookie2)) {
|
|
493
|
-
for (const sc of setCookie2) {
|
|
494
|
-
token = findSetCookie(sc, sessionName);
|
|
495
|
-
if (token) {
|
|
496
|
-
break;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
if (!token) {
|
|
502
|
-
const cookieHeader = _getReqHeader(event, "cookie");
|
|
503
|
-
if (cookieHeader) {
|
|
504
|
-
token = parse(String(cookieHeader))[sessionName];
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
return token;
|
|
508
|
-
}
|
|
509
|
-
function _getReqHeader(event, name) {
|
|
510
|
-
if (event.node) {
|
|
511
|
-
return event.node.req.headers[name];
|
|
512
|
-
}
|
|
513
|
-
if (event.request) {
|
|
514
|
-
return event.request.headers.get(name);
|
|
515
|
-
}
|
|
516
|
-
if (event.headers) {
|
|
517
|
-
return event.headers.get(name);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
function _getResHeader(event, name) {
|
|
521
|
-
if (event.node) {
|
|
522
|
-
return event.node?.res.getHeader(name);
|
|
523
|
-
}
|
|
524
|
-
if (event.response) {
|
|
525
|
-
return event.response.headers?.get(name);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
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
|
-
}
|
|
534
|
-
const sessionName = config.name || DEFAULT_NAME;
|
|
535
|
-
const session = event.context.sessions?.[sessionName] || await getJWSSession(event, config);
|
|
536
|
-
if (typeof update === "function") {
|
|
537
|
-
update = update(session.data);
|
|
538
|
-
}
|
|
539
|
-
if (update) {
|
|
540
|
-
const oldSession = { ...session, data: { ...session.data } };
|
|
541
|
-
Object.assign(session.data, update);
|
|
542
|
-
await config.hooks?.onUpdate?.({
|
|
543
|
-
session,
|
|
544
|
-
oldSession,
|
|
545
|
-
event,
|
|
546
|
-
config
|
|
547
|
-
});
|
|
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
|
-
});
|
|
556
|
-
if (config.cookie !== false) {
|
|
557
|
-
const token = await signJWSSession(event, config);
|
|
558
|
-
setCookie(event, sessionName, token, {
|
|
559
|
-
...DEFAULT_COOKIE,
|
|
560
|
-
...config.cookie,
|
|
561
|
-
expires: config.maxAge === void 0 ? void 0 : new Date(
|
|
562
|
-
session.createdAt + computeExpiresInSeconds(config.maxAge) * 1e3
|
|
563
|
-
)
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
return session;
|
|
567
|
-
}
|
|
568
|
-
async function signJWSSession(event, config) {
|
|
569
|
-
const key = getSignKey(config.key);
|
|
570
|
-
const sessionName = config.name || DEFAULT_NAME;
|
|
571
|
-
const session = event.context.sessions?.[sessionName] || await getJWSSession(event, config);
|
|
572
|
-
const iat = Math.floor(session.createdAt / 1e3);
|
|
573
|
-
const exp = session.expiresAt ? Math.floor(session.expiresAt / 1e3) : void 0;
|
|
574
|
-
const payload = {
|
|
575
|
-
...session.data,
|
|
576
|
-
jti: session.id,
|
|
577
|
-
iat
|
|
578
|
-
};
|
|
579
|
-
if (exp) {
|
|
580
|
-
payload.exp = exp;
|
|
581
|
-
}
|
|
582
|
-
let typ = void 0;
|
|
583
|
-
if (config.jws?.signOptions?.protectedHeader?.typ && typeof config.jws.signOptions.protectedHeader.typ === "string" && config.jws.signOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
|
|
584
|
-
typ = config.jws.signOptions.protectedHeader.typ;
|
|
585
|
-
}
|
|
586
|
-
const token = await sign(payload, key, {
|
|
587
|
-
...config.jws?.signOptions,
|
|
588
|
-
expiresIn: void 0,
|
|
589
|
-
// controlled via 'exp' claim
|
|
590
|
-
protectedHeader: {
|
|
591
|
-
...config.jws?.signOptions?.protectedHeader,
|
|
592
|
-
kid: key.kid,
|
|
593
|
-
typ: typ || "JWT",
|
|
594
|
-
cty: "application/json"
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
return token;
|
|
598
|
-
}
|
|
599
|
-
async function verifyJWSSession(event, config, token) {
|
|
600
|
-
const alg = config.jws?.signOptions?.alg;
|
|
601
|
-
const jwk = config.hooks?.onVerifyKeyLookup ? (header) => config.hooks.onVerifyKeyLookup({
|
|
602
|
-
header,
|
|
603
|
-
event,
|
|
604
|
-
config
|
|
605
|
-
}) : getVerifyKey(config.key);
|
|
606
|
-
let typ = void 0;
|
|
607
|
-
if (config.jws?.signOptions?.protectedHeader?.typ && typeof config.jws.signOptions.protectedHeader.typ === "string" && config.jws.signOptions.protectedHeader.typ.toLowerCase().includes("jwt")) {
|
|
608
|
-
typ = config.jws.signOptions.protectedHeader.typ;
|
|
609
|
-
}
|
|
610
|
-
const { payload } = await verify(token, jwk, {
|
|
611
|
-
...config.jws?.verifyOptions,
|
|
612
|
-
requiredClaims: [
|
|
613
|
-
.../* @__PURE__ */ new Set([
|
|
614
|
-
...config.jws?.verifyOptions?.requiredClaims || [],
|
|
615
|
-
"jti",
|
|
616
|
-
"iat"
|
|
617
|
-
])
|
|
618
|
-
],
|
|
619
|
-
typ: typ || "JWT",
|
|
620
|
-
algorithms: alg ? [alg] : void 0,
|
|
621
|
-
forceUint8Array: false,
|
|
622
|
-
validateJWT: true
|
|
623
|
-
}).catch((error_) => {
|
|
624
|
-
const message = error_ instanceof Error ? error_.message : String(error_);
|
|
625
|
-
throw new Error(`Invalid session token: ${message}`);
|
|
626
|
-
});
|
|
627
|
-
const { jti, iat, exp, ...data } = payload;
|
|
628
|
-
return {
|
|
629
|
-
id: jti,
|
|
630
|
-
createdAt: iat * 1e3,
|
|
631
|
-
// Convert back to ms
|
|
632
|
-
expiresAt: exp ? exp * 1e3 : void 0,
|
|
633
|
-
data: data && typeof data === "object" ? data : /* @__PURE__ */ Object.create(null)
|
|
634
|
-
};
|
|
635
|
-
}
|
|
636
|
-
async function clearJWSSession(event, config) {
|
|
637
|
-
const sessionName = config.name || DEFAULT_NAME;
|
|
638
|
-
let session = event.context.sessions?.[sessionName];
|
|
639
|
-
if (session && session[kGetSessionPromise]) {
|
|
640
|
-
session = await session[kGetSessionPromise];
|
|
641
|
-
}
|
|
642
|
-
if (event.context.sessions?.[sessionName]) {
|
|
643
|
-
delete event.context.sessions[sessionName];
|
|
644
|
-
}
|
|
645
|
-
setCookie(event, sessionName, "", {
|
|
646
|
-
...DEFAULT_COOKIE,
|
|
647
|
-
...config.cookie,
|
|
648
|
-
expires: /* @__PURE__ */ new Date(0),
|
|
649
|
-
maxAge: void 0
|
|
650
|
-
});
|
|
651
|
-
await config.hooks?.onClear?.({
|
|
652
|
-
session,
|
|
653
|
-
event,
|
|
654
|
-
config
|
|
655
|
-
});
|
|
656
|
-
}
|
|
657
|
-
function getSignKey(key) {
|
|
658
|
-
if (!key) {
|
|
659
|
-
throw new Error("Session: JWS key is required.");
|
|
660
|
-
}
|
|
661
|
-
let _key = void 0;
|
|
662
|
-
if (isSymmetricJWK(key)) {
|
|
663
|
-
_key = key;
|
|
664
|
-
} else if ("privateKey" in key && isPrivateJWK(key.privateKey)) {
|
|
665
|
-
_key = key.privateKey;
|
|
666
|
-
}
|
|
667
|
-
if (!_key) {
|
|
668
|
-
throw new Error(
|
|
669
|
-
"Session: Invalid JWS key. It must be a symmetric JWK or a private JWK.",
|
|
670
|
-
{ cause: key }
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
return _key;
|
|
674
|
-
}
|
|
675
|
-
function getVerifyKey(key) {
|
|
676
|
-
if (!key) {
|
|
677
|
-
throw new Error("Session: JWS key is required.");
|
|
678
|
-
}
|
|
679
|
-
let _key = void 0;
|
|
680
|
-
if (isSymmetricJWK(key)) {
|
|
681
|
-
_key = key;
|
|
682
|
-
} else if ("publicKey" in key && isPublicJWK(key.publicKey)) {
|
|
683
|
-
_key = key.publicKey;
|
|
684
|
-
} else if ("publicKey" in key && Array.isArray(key.publicKey)) {
|
|
685
|
-
const keys = key.publicKey.filter((k) => isPublicJWK(k));
|
|
686
|
-
if (keys && keys.length > 0) {
|
|
687
|
-
_key = { keys };
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
if (!_key) {
|
|
691
|
-
throw new Error(
|
|
692
|
-
"Session: Invalid JWS key. It must be a symmetric JWK or a public JWK/set.",
|
|
693
|
-
{ cause: key }
|
|
694
|
-
);
|
|
695
|
-
}
|
|
696
|
-
return _key;
|
|
697
|
-
}
|
|
698
|
-
function findSetCookie(setCookie2, name) {
|
|
699
|
-
const regex = new RegExp(`(?:^|,\\s*)${name}=([^;]+)`);
|
|
700
|
-
const match = setCookie2.match(regex);
|
|
701
|
-
return match ? match[1] : void 0;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
export { clearJWESession, clearJWSSession, getJWESession, getJWESessionToken, getJWSSession, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession };
|
|
1
|
+
import { a as deriveJWKFromPassword, c as importJWKFromPEM, o as exportJWKToPEM, s as generateJWK } from "../_chunks/jws.mjs";
|
|
2
|
+
import { a as useJWSSession, c as getJWESession, d as unsealJWESession, f as updateJWESession, i as updateJWSSession, l as getJWESessionToken, n as getJWSSession, o as verifyJWSSession, p as useJWESession, r as signJWSSession, s as clearJWESession, t as clearJWSSession, u as sealJWESession } from "../_chunks/jws2.mjs";
|
|
3
|
+
export { clearJWESession, clearJWSSession, deriveJWKFromPassword, exportJWKToPEM, generateJWK, getJWESession, getJWESessionToken, getJWSSession, importJWKFromPEM, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession };
|