unjwt 0.5.38 → 0.5.39

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