unjwt 0.5.25 → 0.5.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,8 @@ A collection of low-level JWT ([RFC 7519](https://datatracker.ietf.org/doc/html/
15
15
  - **JWK (JSON Web Key, [RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517))**: generate, import, export, wrap, and unwrap keys in JWK format or as `CryptoKey` objects.
16
16
 
17
17
  - **Adapters** for popular frameworks (PRs welcome for more!):
18
- - [H3 (Nuxt, Nitro)](./src/adapters/h3.ts): `useJWSSession()`, `useJWESession()`
18
+ - [H3 v1 (Nuxt v4, Nitro v2)](./src/adapters/h3v1/): `useJWSSession()`, `useJWESession()`
19
+ - [H3 v2 (Nuxt v5, Nitro v3)](./src/adapters/h3v2/): `useJWSSession()`, `useJWESession()`
19
20
 
20
21
  ## Table of Contents
21
22
 
@@ -25,7 +26,8 @@ A collection of low-level JWT ([RFC 7519](https://datatracker.ietf.org/doc/html/
25
26
  - [JWK](#jwk-json-web-key-rfc-7517)
26
27
  - [Utility Functions](#utility-functions)
27
28
  - [Adapters](#adapters)
28
- - [H3 (Nuxt, Nitro)](#h3-nuxt-nitro)
29
+ - [H3 v1 (Nuxt up to v4, Nitro up to v2)](#h3-v1-nuxt-v4-nitro-v2)
30
+ - [H3 v2 (Nuxt v5, Nitro v3)](#h3-v2-nuxt-v5-nitro-v3)
29
31
  - [Development](#development)
30
32
  - [Credits](#credits)
31
33
  - [License](#license)
@@ -616,7 +618,7 @@ Both helpers expose the same API: read `session.id` / `session.data`, call `sess
616
618
  import { defineEventHandler } from "h3";
617
619
  import { useJWESession, useJWSSession, generateJWK } from "unjwt/adapters/h3v1";
618
620
 
619
- const keys = await generateJWK("RS256");
621
+ const keys = await generateJWK("RS256"); // Make sure to persist these keys somewhere!
620
622
 
621
623
  export default defineEventHandler(async (event) => {
622
624
  const privateSession = await useJWESession(event, {
@@ -663,7 +665,7 @@ import {
663
665
  generateJWK,
664
666
  } from "unjwt/adapters/h3v2";
665
667
 
666
- const atJwk = await generateJWK("RS256");
668
+ const atJwk = await generateJWK("RS256"); // Make sure to persist these keys somewhere!
667
669
 
668
670
  const jweOptions = {
669
671
  key: "refresh_token_secret",
@@ -675,7 +677,7 @@ const jwsOptions = {
675
677
  name: "access_token",
676
678
  maxAge: 15 * 60, // 15 minutes
677
679
  hooks: {
678
- async onExpire(event, _error, config) {
680
+ async onExpire({ event, config }) {
679
681
  const refreshSession = await getJWESession(event, jweOptions);
680
682
  if (!refreshSession.data.sub) {
681
683
  // no valid refresh session, nothing to do
@@ -7,38 +7,62 @@ import { H3Event } from 'h3';
7
7
  import { c as JWSSignOptions } from '../shared/unjwt.BsLgL0DQ.mjs';
8
8
  export { d as deriveJWKFromPassword, e as exportJWKToPEM, g as generateJWK, i as importJWKFromPEM } from '../shared/unjwt.BjP_dGnX.mjs';
9
9
 
10
+ type SessionData<T extends JWTClaims = JWTClaims> = Omit<T, "jti" | "iat" | "exp">;
11
+ type SessionUpdate<T extends JWTClaims = JWTClaims> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
12
+ interface SessionManager<T extends JWTClaims = JWTClaims, ConfigMaxAge extends number | undefined = number | undefined> {
13
+ readonly id: string | undefined;
14
+ readonly createdAt: number;
15
+ readonly expiresAt: T extends {
16
+ exp: number;
17
+ } ? number : ConfigMaxAge;
18
+ readonly data: SessionData<T>;
19
+ update: (update: SessionUpdate<T>) => Promise<SessionManager<T>>;
20
+ clear: () => Promise<SessionManager<T>>;
21
+ }
22
+
10
23
  /**
11
24
  * This is a fork of h3 library's session utility functions.
12
25
  * @source https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/src/utils/session.ts
13
26
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
14
27
  */
15
28
 
16
- type SessionDataT$1 = Omit<JWTClaims, "jti" | "iat" | "exp">;
17
- type SessionData<T extends SessionDataT$1 = SessionDataT$1> = T;
18
29
  declare const kGetSessionPromise$1: unique symbol;
19
- interface SessionJWE<T extends SessionDataT$1 = SessionDataT$1> {
30
+ interface SessionJWE<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
20
31
  id: string;
21
32
  createdAt: number;
22
- expiresAt?: number;
33
+ expiresAt: T extends {
34
+ exp: number;
35
+ } ? number : MaxAge;
23
36
  data: SessionData<T>;
24
- [kGetSessionPromise$1]?: Promise<SessionJWE<T>>;
37
+ [kGetSessionPromise$1]?: Promise<SessionJWE<T, MaxAge>>;
25
38
  }
26
- interface SessionHooksJWE {
27
- onRead?: (session: SessionJWE, event: H3Event, config: SessionConfigJWE) => void | Promise<void>;
28
- onUpdate?: (session: SessionJWE, event: H3Event, config: SessionConfigJWE) => void | Promise<void>;
29
- onClear?: (event: H3Event, config: Partial<SessionConfigJWE>) => void | Promise<void>;
30
- onExpire?: (event: H3Event, error: any | undefined, config: SessionConfigJWE) => void | Promise<void>;
31
- onError?: (event: H3Event, error: any, config: SessionConfigJWE) => void | Promise<void>;
32
- }
33
- interface SessionManager<T extends SessionDataT$1 = SessionDataT$1> {
34
- readonly id: string | undefined;
35
- readonly createdAt: number;
36
- readonly expiresAt: number | undefined;
37
- readonly data: SessionData<T>;
38
- update: (update: SessionUpdate$1<T>) => Promise<SessionManager<T>>;
39
- clear: () => Promise<SessionManager<T>>;
39
+ interface SessionHooksJWE<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
40
+ onRead?: (args: {
41
+ session: SessionJWE<T, MaxAge>;
42
+ event: H3Event;
43
+ config: SessionConfigJWE<T, MaxAge>;
44
+ }) => void | Promise<void>;
45
+ onUpdate?: (args: {
46
+ session: SessionJWE<T, MaxAge>;
47
+ event: H3Event;
48
+ config: SessionConfigJWE<T, MaxAge>;
49
+ }) => void | Promise<void>;
50
+ onClear?: (args: {
51
+ event: H3Event;
52
+ config: Partial<SessionConfigJWE<T, MaxAge>>;
53
+ }) => void | Promise<void>;
54
+ onExpire?: (args: {
55
+ event: H3Event;
56
+ error: Error;
57
+ config: SessionConfigJWE<T, MaxAge>;
58
+ }) => void | Promise<void>;
59
+ onError?: (args: {
60
+ event: H3Event;
61
+ error: any;
62
+ config: SessionConfigJWE<T, MaxAge>;
63
+ }) => void | Promise<void>;
40
64
  }
41
- interface SessionConfigJWE {
65
+ interface SessionConfigJWE<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
42
66
  /** @deprecated use `key` instead */
43
67
  secret?: string | JWK_Symmetric | {
44
68
  privateKey: JWK_Private | JWK_Symmetric;
@@ -50,7 +74,7 @@ interface SessionConfigJWE {
50
74
  publicKey?: JWK_Public;
51
75
  };
52
76
  /** Session lifetime in seconds (used to derive exp from iat) */
53
- maxAge?: number;
77
+ maxAge?: MaxAge;
54
78
  /** Default is "h3" */
55
79
  name?: string;
56
80
  /** Default is secure, httpOnly, path="/" */
@@ -64,7 +88,7 @@ interface SessionConfigJWE {
64
88
  encryptOptions?: Omit<JWEEncryptOptions, "expiresIn">;
65
89
  decryptOptions?: JWTClaimValidationOptions;
66
90
  };
67
- hooks?: SessionHooksJWE;
91
+ hooks?: SessionHooksJWE<T, MaxAge>;
68
92
  }
69
93
  /**
70
94
  * @deprecated use `SessionConfigJWE` instead
@@ -79,19 +103,18 @@ type CompatEvent$1 = {
79
103
  headers: Headers;
80
104
  context: any;
81
105
  };
82
- type SessionUpdate$1<T extends SessionDataT$1 = SessionDataT$1> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
83
106
  /**
84
107
  * Create a session manager for the current request.
85
108
  */
86
- declare function useJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: H3Event | CompatEvent$1, config: SessionConfigJWE): Promise<SessionManager<T>>;
109
+ declare function useJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event | CompatEvent$1, config: SessionConfigJWE<T, MaxAge>): Promise<SessionManager<T, MaxAge>>;
87
110
  /**
88
111
  * Get (and lazily initialize) the session for the current request.
89
112
  */
90
- declare function getJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: H3Event | CompatEvent$1, config: SessionConfigJWE): Promise<SessionJWE<T>>;
113
+ declare function getJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event | CompatEvent$1, config: SessionConfigJWE<T, MaxAge>): Promise<SessionJWE<T, MaxAge>>;
91
114
  /**
92
115
  * Update the session (optionally mutating the session data) and re-issue the JWE token.
93
116
  */
94
- declare function updateJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: H3Event, config: SessionConfigJWE, update?: SessionUpdate$1<T>): Promise<SessionJWE<T>>;
117
+ declare function updateJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event, config: SessionConfigJWE<T, MaxAge>, update?: SessionUpdate<T>): Promise<SessionJWE<T, MaxAge>>;
95
118
  /**
96
119
  * Produce a JWE for the current session.
97
120
  * Payload structure:
@@ -102,15 +125,15 @@ declare function updateJWESession<T extends SessionDataT$1 = SessionDataT$1>(eve
102
125
  * data: Record<string, any>;
103
126
  * }
104
127
  */
105
- declare function sealJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: H3Event | CompatEvent$1, config: SessionConfigJWE): Promise<string>;
128
+ declare function sealJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event | CompatEvent$1, config: SessionConfigJWE<T, MaxAge>): Promise<string>;
106
129
  /**
107
130
  * Decrypt the JWE and return a Session-compatible object.
108
131
  */
109
- declare function unsealJWESession(_event: H3Event | CompatEvent$1, config: SessionConfigJWE, sealed: string): Promise<Partial<SessionJWE>>;
132
+ declare function unsealJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(_event: H3Event | CompatEvent$1, config: SessionConfigJWE<T, MaxAge>, sealed: string): Promise<Partial<SessionJWE<T, MaxAge>>>;
110
133
  /**
111
134
  * Clear the session (delete from context and drop cookie).
112
135
  */
113
- declare function clearJWESession(event: H3Event, config: Partial<SessionConfigJWE>): Promise<void>;
136
+ declare function clearJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event, config: Partial<SessionConfigJWE<T, MaxAge>>): Promise<void>;
114
137
 
115
138
  /**
116
139
  * This is a fork of h3 library's session utility functions.
@@ -118,23 +141,43 @@ declare function clearJWESession(event: H3Event, config: Partial<SessionConfigJW
118
141
  * @license MIT https://github.com/h3js/h3/blob/b4dce71c256911335f3402d09f30ffad120ad61a/LICENSE
119
142
  */
120
143
 
121
- type SessionDataT = Omit<JWTClaims, "jti" | "iat" | "exp">;
122
144
  declare const kGetSessionPromise: unique symbol;
123
- interface SessionJWS<T extends SessionDataT = SessionDataT> {
145
+ interface SessionJWS<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
124
146
  id: string;
125
147
  createdAt: number;
126
- expiresAt?: number;
148
+ expiresAt: T extends {
149
+ exp: number;
150
+ } ? number : MaxAge;
127
151
  data: SessionData<T>;
128
- [kGetSessionPromise]?: Promise<SessionJWS<T>>;
152
+ [kGetSessionPromise]?: Promise<SessionJWS<T, MaxAge>>;
129
153
  }
130
- interface SessionHooksJWS {
131
- onRead?: (session: SessionJWS, event: H3Event, config: SessionConfigJWS) => void | Promise<void>;
132
- onUpdate?: (session: SessionJWS, event: H3Event, config: SessionConfigJWS) => void | Promise<void>;
133
- onClear?: (event: H3Event, config: Partial<SessionConfigJWS>) => void | Promise<void>;
134
- onExpire?: (event: H3Event, error: any | undefined, config: SessionConfigJWS) => void | Promise<void>;
135
- onError?: (event: H3Event, error: any, config: SessionConfigJWS) => void | Promise<void>;
154
+ interface SessionHooksJWS<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
155
+ onRead?: (args: {
156
+ session: SessionJWS<T, MaxAge>;
157
+ event: H3Event;
158
+ config: SessionConfigJWS<T, MaxAge>;
159
+ }) => void | Promise<void>;
160
+ onUpdate?: (args: {
161
+ session: SessionJWS<T, MaxAge>;
162
+ event: H3Event;
163
+ config: SessionConfigJWS<T, MaxAge>;
164
+ }) => void | Promise<void>;
165
+ onClear?: (args: {
166
+ event: H3Event;
167
+ config: Partial<SessionConfigJWS<T, MaxAge>>;
168
+ }) => void | Promise<void>;
169
+ onExpire?: (args: {
170
+ event: H3Event;
171
+ error: Error;
172
+ config: SessionConfigJWS<T, MaxAge>;
173
+ }) => void | Promise<void>;
174
+ onError?: (args: {
175
+ event: H3Event;
176
+ error: any;
177
+ config: SessionConfigJWS<T, MaxAge>;
178
+ }) => void | Promise<void>;
136
179
  }
137
- interface SessionConfigJWS {
180
+ interface SessionConfigJWS<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
138
181
  /**
139
182
  * JWK (private for signing with RS/ES/PS, or symmetric oct) used for signing.
140
183
  */
@@ -143,7 +186,7 @@ interface SessionConfigJWS {
143
186
  publicKey: JWK_Public | JWK_Public[] | JWKSet;
144
187
  };
145
188
  /** Session lifetime in seconds (sets exp = iat + maxAge) */
146
- maxAge?: number;
189
+ maxAge?: MaxAge;
147
190
  /** Default cookie / header name base */
148
191
  name?: string;
149
192
  /** Cookie options (false to disable cookies) */
@@ -157,7 +200,7 @@ interface SessionConfigJWS {
157
200
  signOptions?: Omit<JWSSignOptions, "expiresIn">;
158
201
  verifyOptions?: JWTClaimValidationOptions;
159
202
  };
160
- hooks?: SessionHooksJWS;
203
+ hooks?: SessionHooksJWS<T, MaxAge>;
161
204
  }
162
205
  /**
163
206
  * @deprecated use `SessionConfigJWS` instead
@@ -172,26 +215,25 @@ type CompatEvent = {
172
215
  headers: Headers;
173
216
  context: any;
174
217
  };
175
- type SessionUpdate<T extends SessionDataT = SessionDataT> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
176
218
  /**
177
219
  * Create a session manager for the current request using JWS (signed only, not encrypted).
178
220
  * NOTE: Contents are visible to clients (Base64URL-decoded JSON). Do not store secrets in session data.
179
221
  */
180
- declare function useJWSSession<T extends SessionDataT = SessionDataT>(event: H3Event | CompatEvent, config: SessionConfigJWS): Promise<SessionManager<T>>;
222
+ declare function useJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event | CompatEvent, config: SessionConfigJWS<T, MaxAge>): Promise<SessionManager<T, MaxAge>>;
181
223
  /**
182
224
  * Retrieve (and lazily initialize) the session.
183
225
  */
184
- declare function getJWSSession<T extends SessionDataT = SessionDataT>(event: H3Event | CompatEvent, config: SessionConfigJWS): Promise<SessionJWS<T>>;
226
+ declare function getJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event | CompatEvent, config: SessionConfigJWS<T, MaxAge>): Promise<SessionJWS<T, MaxAge>>;
185
227
  /**
186
228
  * Update session data (if provided) and reissue JWS.
187
229
  */
188
- declare function updateJWSSession<T extends SessionDataT = SessionDataT>(event: H3Event, config: SessionConfigJWS, update?: SessionUpdate<T>): Promise<SessionJWS<T>>;
230
+ declare function updateJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event, config: SessionConfigJWS<T, MaxAge>, update?: SessionUpdate<T>): Promise<SessionJWS<T, MaxAge>>;
189
231
  /**
190
232
  * Sign current session as a compact JWS.
191
233
  * Payload claims:
192
234
  * jti, iat, exp?, data, plus optional extraClaims (cannot override reserved)
193
235
  */
194
- declare function signJWSSession<T extends SessionDataT = SessionDataT>(event: H3Event | CompatEvent, config: SessionConfigJWS): Promise<string>;
236
+ declare function signJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event | CompatEvent, config: SessionConfigJWS<T, MaxAge>): Promise<string>;
195
237
  /**
196
238
  * Verify and parse a compact JWS into a Session structure.
197
239
  * Performs:
@@ -200,11 +242,11 @@ declare function signJWSSession<T extends SessionDataT = SessionDataT>(event: H3
200
242
  * - ensures jti & iat presence
201
243
  * - enforces maxAge if provided
202
244
  */
203
- declare function verifyJWSSession(_event: H3Event | CompatEvent, config: SessionConfigJWS, token: string): Promise<Partial<SessionJWS>>;
245
+ declare function verifyJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(_event: H3Event | CompatEvent, config: SessionConfigJWS<T, MaxAge>, token: string): Promise<Partial<SessionJWS<T, MaxAge>>>;
204
246
  /**
205
247
  * Destroy the session (context + cookie).
206
248
  */
207
- declare function clearJWSSession(event: H3Event, config: Partial<SessionConfigJWS>): Promise<void>;
249
+ declare function clearJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: H3Event, config: Partial<SessionConfigJWS<T, MaxAge>>): Promise<void>;
208
250
 
209
251
  export { JWEEncryptOptions, JWKSet, JWK_Private, JWK_Public, JWK_Symmetric, JWTClaimValidationOptions, JWTClaims, clearJWESession, clearJWSSession, getJWESession, getJWSSession, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession };
210
- export type { SessionConfigJWE, SessionConfigJWS, SessionData, SessionHooksJWE, SessionHooksJWS, SessionJWE, SessionJWEConfig, SessionJWS, SessionJWSConfig, SessionManager };
252
+ export type { SessionConfigJWE, SessionConfigJWS, SessionData, SessionHooksJWE, SessionHooksJWS, SessionJWE, SessionJWEConfig, SessionJWS, SessionJWSConfig, SessionManager, SessionUpdate };
@@ -59,12 +59,22 @@ async function getJWESession(event, config) {
59
59
  if (existingSession) {
60
60
  const session2 = existingSession[kGetSessionPromise$1] ? await existingSession[kGetSessionPromise$1] : existingSession;
61
61
  if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && isEvent(event)) {
62
- await config.hooks?.onExpire?.(event, void 0, config);
62
+ await config.hooks?.onExpire?.({
63
+ event,
64
+ error: new Error(
65
+ `JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${new Date(session2.expiresAt * 1e3).toISOString()})`
66
+ ),
67
+ config
68
+ });
63
69
  return clearJWESession(event, config).then(
64
70
  () => getJWESession(event, config)
65
71
  );
66
72
  }
67
- await config.hooks?.onRead?.(session2, event, config);
73
+ await config.hooks?.onRead?.({
74
+ event,
75
+ session: session2,
76
+ config
77
+ });
68
78
  return session2;
69
79
  }
70
80
  const session = {
@@ -74,27 +84,35 @@ async function getJWESession(event, config) {
74
84
  data: /* @__PURE__ */ Object.create(null)
75
85
  };
76
86
  event.context.sessions[sessionName] = session;
77
- let jweToken;
87
+ let token;
78
88
  if (config.sessionHeader !== false) {
79
89
  const headerName = typeof config.sessionHeader === "string" ? config.sessionHeader.toLowerCase() : `x-${sessionName.toLowerCase()}-session`;
80
90
  const headerValue = _getReqHeader$1(event, headerName);
81
91
  if (typeof headerValue === "string") {
82
- jweToken = headerValue;
92
+ token = headerValue.startsWith("Bearer ") ? headerValue.slice(7).trim() : headerValue;
83
93
  }
84
94
  }
85
- if (!jweToken) {
95
+ if (!token) {
86
96
  const cookieHeader = _getReqHeader$1(event, "cookie");
87
97
  if (cookieHeader) {
88
- jweToken = parse(String(cookieHeader))[sessionName];
98
+ token = parse(String(cookieHeader))[sessionName];
89
99
  }
90
100
  }
91
- if (jweToken) {
92
- const promise = unsealJWESession(event, config, jweToken).catch(async (error_) => {
101
+ if (token) {
102
+ const promise = unsealJWESession(event, config, token).catch(async (error_) => {
93
103
  if (error_ instanceof Error && (error_.message.includes("Token has expired") || error_.message.includes("Token is too old"))) {
94
- await config.hooks?.onExpire?.(event, error_, config);
104
+ await config.hooks?.onExpire?.({
105
+ event,
106
+ error: error_,
107
+ config
108
+ });
95
109
  return void 0;
96
110
  }
97
- await config.hooks?.onError?.(event, error_, config);
111
+ await config.hooks?.onError?.({
112
+ event,
113
+ error: error_,
114
+ config
115
+ });
98
116
  return void 0;
99
117
  }).then((unsealed) => {
100
118
  if (unsealed) {
@@ -117,7 +135,11 @@ async function getJWESession(event, config) {
117
135
  session.expiresAt = config.maxAge ? session.createdAt + config.maxAge * 1e3 : void 0;
118
136
  await updateJWESession(event, config);
119
137
  }
120
- await config.hooks?.onRead?.(session, event, config);
138
+ await config.hooks?.onRead?.({
139
+ event,
140
+ session,
141
+ config
142
+ });
121
143
  return session;
122
144
  }
123
145
  function _getReqHeader$1(event, name) {
@@ -139,7 +161,11 @@ async function updateJWESession(event, config, update) {
139
161
  }
140
162
  if (update) {
141
163
  Object.assign(session.data, update);
142
- await config.hooks?.onUpdate?.(session, event, config);
164
+ await config.hooks?.onUpdate?.({
165
+ event,
166
+ session,
167
+ config
168
+ });
143
169
  }
144
170
  if (config.cookie !== false) {
145
171
  const sealed = await sealJWESession(event, config);
@@ -195,11 +221,11 @@ async function unsealJWESession(_event, config, sealed) {
195
221
  const { payload } = await decrypt(sealed, key, {
196
222
  ...config.jwe?.decryptOptions,
197
223
  requiredClaims: [
198
- ...config.jwe?.decryptOptions?.requiredClaims?.filter(
199
- (claim) => claim !== "jti" && claim !== "iat"
200
- ) || [],
201
- "jti",
202
- "iat"
224
+ .../* @__PURE__ */ new Set([
225
+ ...config.jwe?.decryptOptions?.requiredClaims || [],
226
+ "jti",
227
+ "iat"
228
+ ])
203
229
  ],
204
230
  maxTokenAge: config.maxAge,
205
231
  algorithms: alg ? [alg] : void 0,
@@ -235,7 +261,10 @@ async function clearJWESession(event, config) {
235
261
  expires: /* @__PURE__ */ new Date(0),
236
262
  maxAge: void 0
237
263
  });
238
- await config.hooks?.onClear?.(event, config);
264
+ await config.hooks?.onClear?.({
265
+ event,
266
+ config
267
+ });
239
268
  }
240
269
  function getEncryptKey(key) {
241
270
  if (!key) {
@@ -334,12 +363,22 @@ async function getJWSSession(event, config) {
334
363
  if (existingSession) {
335
364
  const session2 = existingSession[kGetSessionPromise] ? await existingSession[kGetSessionPromise] : existingSession;
336
365
  if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && isEvent(event)) {
337
- await config.hooks?.onExpire?.(event, void 0, config);
366
+ await config.hooks?.onExpire?.({
367
+ event,
368
+ error: new Error(
369
+ `JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${new Date(session2.expiresAt * 1e3).toISOString()})`
370
+ ),
371
+ config
372
+ });
338
373
  return clearJWSSession(event, config).then(
339
374
  () => getJWSSession(event, config)
340
375
  );
341
376
  }
342
- await config.hooks?.onRead?.(session2, event, config);
377
+ await config.hooks?.onRead?.({
378
+ event,
379
+ session: session2,
380
+ config
381
+ });
343
382
  return session2;
344
383
  }
345
384
  const session = {
@@ -354,7 +393,7 @@ async function getJWSSession(event, config) {
354
393
  const headerName = typeof config.sessionHeader === "string" ? config.sessionHeader.toLowerCase() : `x-${sessionName.toLowerCase()}-session`;
355
394
  const headerValue = _getReqHeader(event, headerName);
356
395
  if (typeof headerValue === "string") {
357
- token = headerValue;
396
+ token = headerValue.startsWith("Bearer ") ? headerValue.slice(7).trim() : headerValue;
358
397
  }
359
398
  }
360
399
  if (!token) {
@@ -366,10 +405,18 @@ async function getJWSSession(event, config) {
366
405
  if (token) {
367
406
  const promise = verifyJWSSession(event, config, token).catch(async (error_) => {
368
407
  if (error_ instanceof Error && (error_.message.includes("Token has expired") || error_.message.includes("Token is too old"))) {
369
- await config.hooks?.onExpire?.(event, error_, config);
408
+ await config.hooks?.onExpire?.({
409
+ event,
410
+ error: error_,
411
+ config
412
+ });
370
413
  return void 0;
371
414
  }
372
- await config.hooks?.onError?.(event, error_, config);
415
+ await config.hooks?.onError?.({
416
+ event,
417
+ error: error_,
418
+ config
419
+ });
373
420
  return void 0;
374
421
  }).then((unsealed) => {
375
422
  if (unsealed) {
@@ -392,7 +439,11 @@ async function getJWSSession(event, config) {
392
439
  session.expiresAt = config.maxAge ? session.createdAt + config.maxAge * 1e3 : void 0;
393
440
  await updateJWSSession(event, config);
394
441
  }
395
- await config.hooks?.onRead?.(session, event, config);
442
+ await config.hooks?.onRead?.({
443
+ event,
444
+ session,
445
+ config
446
+ });
396
447
  return session;
397
448
  }
398
449
  function _getReqHeader(event, name) {
@@ -414,7 +465,11 @@ async function updateJWSSession(event, config, update) {
414
465
  }
415
466
  if (update) {
416
467
  Object.assign(session.data, update);
417
- await config.hooks?.onUpdate?.(session, event, config);
468
+ await config.hooks?.onUpdate?.({
469
+ event,
470
+ session,
471
+ config
472
+ });
418
473
  }
419
474
  if (config.cookie !== false) {
420
475
  const token = await signJWSSession(event, config);
@@ -467,11 +522,11 @@ async function verifyJWSSession(_event, config, token) {
467
522
  const { payload } = await verify(token, jwk, {
468
523
  ...config.jws?.verifyOptions,
469
524
  requiredClaims: [
470
- ...config.jws?.verifyOptions?.requiredClaims?.filter(
471
- (claim) => claim !== "jti" && claim !== "iat"
472
- ) || [],
473
- "jti",
474
- "iat"
525
+ .../* @__PURE__ */ new Set([
526
+ ...config.jws?.verifyOptions?.requiredClaims || [],
527
+ "jti",
528
+ "iat"
529
+ ])
475
530
  ],
476
531
  typ: typ || "JWT",
477
532
  algorithms: alg ? [alg] : void 0,
@@ -501,7 +556,10 @@ async function clearJWSSession(event, config) {
501
556
  expires: /* @__PURE__ */ new Date(0),
502
557
  maxAge: void 0
503
558
  });
504
- await config.hooks?.onClear?.(event, config);
559
+ await config.hooks?.onClear?.({
560
+ event,
561
+ config
562
+ });
505
563
  }
506
564
  function getSignKey(key) {
507
565
  if (!key) {
@@ -1,6 +1,6 @@
1
1
  export { d as JWEDecryptOptions, e as JWEDecryptResult, b as JWEEncryptOptions, J as JWEHeaderParameters, c as JWEKeyLookupFunction, a as JWEKeyManagementHeaderParameters } from '../shared/unjwt.9mL1vSFP.mjs';
2
2
  export { C as CompositeKey, f as ContentEncryptionAlgorithm, D as DeriveKeyOptions, e as DeriveKeyReturn, c as GenerateJWKOptions, d as GenerateJWKReturn, G as GenerateKeyAlgorithm, a as GenerateKeyOptions, b as GenerateKeyReturn, v as JWK, S as JWKAlgorithm, T as JWKPEMAlgorithm, J as JWKParameters, w as JWKSet, I as JWK_AES_CBC_HMAC, L as JWK_AES_GCM, H as JWK_AES_GCM_KW, F as JWK_AES_KW, s as JWK_Asymmetric, R as JWK_Asymmetric_Algorithm, j as JWK_EC, O as JWK_ECDH_ES, A as JWK_ECDSA, i as JWK_EC_Private, h as JWK_EC_Public, x as JWK_HMAC, p as JWK_OKP, o as JWK_OKP_Private, n as JWK_OKP_Public, P as JWK_OKP_SIGN, N as JWK_PBES2, u as JWK_Private, t as JWK_Public, m as JWK_RSA, B as JWK_RSA_ENC, z as JWK_RSA_PSS, l as JWK_RSA_Private, k as JWK_RSA_Public, y as JWK_RSA_SIGN, r as JWK_Symmetric, Q as JWK_Symmetric_Algorithm, q as JWK_oct, Y as JWT, Z as JWTClaimValidationOptions, X as JWTClaims, V as JoseHeaderParameters, K as KeyManagementAlgorithm, U as UnwrapKeyOptions, W as WrapKeyOptions, g as WrapKeyResult } from '../shared/unjwt.CtHrClHc.mjs';
3
- export { SessionConfigJWE, SessionConfigJWS, SessionData, SessionHooksJWE, SessionHooksJWS, SessionJWE, SessionJWEConfig, SessionJWS, SessionJWSConfig, SessionManager, clearJWESession, clearJWSSession, getJWESession, getJWSSession, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession } from './h3.mjs';
3
+ export { SessionConfigJWE, SessionConfigJWS, SessionData, SessionHooksJWE, SessionHooksJWS, SessionJWE, SessionJWEConfig, SessionJWS, SessionJWSConfig, SessionManager, SessionUpdate, clearJWESession, clearJWSSession, getJWESession, getJWSSession, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession } from './h3.mjs';
4
4
  export { d as deriveJWKFromPassword, e as exportJWKToPEM, g as generateJWK, i as importJWKFromPEM } from '../shared/unjwt.BjP_dGnX.mjs';
5
5
  import 'cookie-es';
6
6
  import 'h3';
@@ -7,39 +7,63 @@ import { CookieSerializeOptions } from 'cookie-es';
7
7
  import { c as JWSSignOptions } from '../shared/unjwt.BsLgL0DQ.mjs';
8
8
  export { d as deriveJWKFromPassword, e as exportJWKToPEM, g as generateJWK, i as importJWKFromPEM } from '../shared/unjwt.BjP_dGnX.mjs';
9
9
 
10
- type SessionDataT$1 = Omit<JWTClaims, "jti" | "iat" | "exp">;
11
- type SessionData<T extends SessionDataT$1 = SessionDataT$1> = T;
10
+ type SessionData<T extends JWTClaims = JWTClaims> = Omit<T, "jti" | "iat" | "exp">;
11
+ type SessionUpdate<T extends JWTClaims = JWTClaims> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
12
+ interface SessionManager<T extends JWTClaims = JWTClaims, ConfigMaxAge extends number | undefined = number | undefined> {
13
+ readonly id: string | undefined;
14
+ readonly createdAt: number;
15
+ readonly expiresAt: T extends {
16
+ exp: number;
17
+ } ? number : ConfigMaxAge;
18
+ readonly data: SessionData<T>;
19
+ update: (update: SessionUpdate<T>) => Promise<SessionManager<T>>;
20
+ clear: () => Promise<SessionManager<T>>;
21
+ }
22
+
12
23
  declare const kGetSessionPromise$1: unique symbol;
13
- interface SessionJWE<T extends SessionDataT$1 = SessionDataT$1> {
24
+ interface SessionJWE<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
14
25
  id: string;
15
26
  createdAt: number;
16
- expiresAt?: number;
27
+ expiresAt: T extends {
28
+ exp: number;
29
+ } ? number : MaxAge;
17
30
  data: SessionData<T>;
18
- [kGetSessionPromise$1]?: Promise<SessionJWE<T>>;
31
+ [kGetSessionPromise$1]?: Promise<SessionJWE<T, MaxAge>>;
19
32
  }
20
- interface SessionHooksJWE {
21
- onRead?: (session: SessionJWE, event: HTTPEvent, config: SessionConfigJWE) => void | Promise<void>;
22
- onUpdate?: (session: SessionJWE, event: HTTPEvent, config: SessionConfigJWE) => void | Promise<void>;
23
- onClear?: (event: HTTPEvent, config: Partial<SessionConfigJWE>) => void | Promise<void>;
24
- onExpire?: (event: HTTPEvent, error: any | undefined, config: SessionConfigJWE) => void | Promise<void>;
25
- onError?: (event: HTTPEvent, error: any, config: SessionConfigJWE) => void | Promise<void>;
26
- }
27
- interface SessionManager<T extends SessionDataT$1 = SessionDataT$1> {
28
- readonly id: string | undefined;
29
- readonly createdAt: number;
30
- readonly expiresAt: number | undefined;
31
- readonly data: SessionData<T>;
32
- update: (update: SessionUpdate$1<T>) => Promise<SessionManager<T>>;
33
- clear: () => Promise<SessionManager<T>>;
33
+ interface SessionHooksJWE<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
34
+ onRead?: (args: {
35
+ session: SessionJWE<T, MaxAge>;
36
+ event: HTTPEvent;
37
+ config: SessionConfigJWE<T, MaxAge>;
38
+ }) => void | Promise<void>;
39
+ onUpdate?: (args: {
40
+ session: SessionJWE<T, MaxAge>;
41
+ event: HTTPEvent;
42
+ config: SessionConfigJWE<T, MaxAge>;
43
+ }) => void | Promise<void>;
44
+ onClear?: (args: {
45
+ event: HTTPEvent;
46
+ config: Partial<SessionConfigJWE<T, MaxAge>>;
47
+ }) => void | Promise<void>;
48
+ onExpire?: (args: {
49
+ event: HTTPEvent;
50
+ error: Error;
51
+ config: SessionConfigJWE<T, MaxAge>;
52
+ }) => void | Promise<void>;
53
+ onError?: (args: {
54
+ event: HTTPEvent;
55
+ error: any;
56
+ config: SessionConfigJWE<T, MaxAge>;
57
+ }) => void | Promise<void>;
34
58
  }
35
- interface SessionConfigJWE {
59
+ interface SessionConfigJWE<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
36
60
  /** Shared secret used, string for PBES2 or Json Web Key (JWK) */
37
61
  key: string | JWK_Symmetric | {
38
62
  privateKey: JWK_Private | JWK_Symmetric;
39
63
  publicKey?: JWK_Public;
40
64
  };
41
65
  /** Session lifetime in seconds (used to derive exp from iat) */
42
- maxAge?: number;
66
+ maxAge?: MaxAge;
43
67
  /** Default is "h3" */
44
68
  name?: string;
45
69
  /** Default is secure, httpOnly, path="/" */
@@ -55,56 +79,75 @@ interface SessionConfigJWE {
55
79
  encryptOptions?: Omit<JWEEncryptOptions, "expiresIn">;
56
80
  decryptOptions?: JWTClaimValidationOptions;
57
81
  };
58
- hooks?: SessionHooksJWE;
82
+ hooks?: SessionHooksJWE<T, MaxAge>;
59
83
  }
60
- type SessionUpdate$1<T extends SessionDataT$1 = SessionDataT$1> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
61
84
  /**
62
85
  * Create a session manager for the current request.
63
86
  */
64
- declare function useJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: HTTPEvent, config: SessionConfigJWE): Promise<SessionManager<T>>;
87
+ declare function useJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: HTTPEvent, config: SessionConfigJWE<T, MaxAge>): Promise<SessionManager<T, MaxAge>>;
65
88
  /**
66
89
  * Get the session for the current request.
67
90
  */
68
- declare function getJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: HTTPEvent, config: SessionConfigJWE): Promise<SessionJWE<T>>;
91
+ declare function getJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: HTTPEvent, config: SessionConfigJWE<T, MaxAge>): Promise<SessionJWE<T, MaxAge>>;
69
92
  /**
70
93
  * Update the session data for the current request.
71
94
  */
72
- declare function updateJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: HTTPEvent, config: SessionConfigJWE, update?: SessionUpdate$1<T>): Promise<SessionJWE<T>>;
95
+ declare function updateJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: HTTPEvent, config: SessionConfigJWE<T, MaxAge>, update?: SessionUpdate<T>): Promise<SessionJWE<T, MaxAge>>;
73
96
  /**
74
97
  * Produce a JWE for the current session.
75
98
  */
76
- declare function sealJWESession<T extends SessionDataT$1 = SessionDataT$1>(event: HTTPEvent, config: SessionConfigJWE): Promise<string>;
99
+ declare function sealJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: HTTPEvent, config: SessionConfigJWE<T, MaxAge>): Promise<string>;
77
100
  /**
78
101
  * Decrypt the JWE and return a Session-compatible object.
79
102
  */
80
- declare function unsealJWESession(_event: HTTPEvent, config: SessionConfigJWE, sealed: string): Promise<Partial<SessionJWE>>;
103
+ declare function unsealJWESession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(_event: HTTPEvent, config: SessionConfigJWE<T, MaxAge>, sealed: string): Promise<Partial<SessionJWE<T, MaxAge>>>;
81
104
  /**
82
105
  * Clear the session (delete from context and drop cookie).
83
106
  */
84
- declare function clearJWESession(event: HTTPEvent, config: Partial<SessionConfigJWE>): Promise<void>;
107
+ declare function clearJWESession<T extends JWTClaims, MaxAge extends number | undefined>(event: HTTPEvent, config: Partial<SessionConfigJWE<T, MaxAge>>): Promise<void>;
85
108
 
86
- type SessionDataT = Omit<JWTClaims, "jti" | "iat" | "exp">;
87
109
  declare const kGetSessionPromise: unique symbol;
88
- interface SessionJWS<T extends SessionDataT = SessionDataT> {
110
+ interface SessionJWS<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
89
111
  id: string;
90
112
  createdAt: number;
91
- expiresAt?: number;
113
+ expiresAt: T extends {
114
+ exp: number;
115
+ } ? number : MaxAge;
92
116
  data: SessionData<T>;
93
- [kGetSessionPromise]?: Promise<SessionJWS<T>>;
117
+ [kGetSessionPromise]?: Promise<SessionJWS<T, MaxAge>>;
94
118
  }
95
- interface SessionHooksJWS {
96
- onRead?: (session: SessionJWS, event: HTTPEvent, config: SessionConfigJWS) => void | Promise<void>;
97
- onUpdate?: (session: SessionJWS, event: HTTPEvent, config: SessionConfigJWS) => void | Promise<void>;
98
- onClear?: (event: HTTPEvent, config: Partial<SessionConfigJWS>) => void | Promise<void>;
99
- onExpire?: (event: HTTPEvent, error: any | undefined, config: SessionConfigJWS) => void | Promise<void>;
100
- onError?: (event: HTTPEvent, error: any, config: SessionConfigJWS) => void | Promise<void>;
119
+ interface SessionHooksJWS<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
120
+ onRead?: (args: {
121
+ session: SessionJWS<T, MaxAge>;
122
+ event: HTTPEvent;
123
+ config: SessionConfigJWS<T, MaxAge>;
124
+ }) => void | Promise<void>;
125
+ onUpdate?: (args: {
126
+ session: SessionJWS<T, MaxAge>;
127
+ event: HTTPEvent;
128
+ config: SessionConfigJWS<T, MaxAge>;
129
+ }) => void | Promise<void>;
130
+ onClear?: (args: {
131
+ event: HTTPEvent;
132
+ config: Partial<SessionConfigJWS<T, MaxAge>>;
133
+ }) => void | Promise<void>;
134
+ onExpire?: (args: {
135
+ event: HTTPEvent;
136
+ error: Error;
137
+ config: SessionConfigJWS<T, MaxAge>;
138
+ }) => void | Promise<void>;
139
+ onError?: (args: {
140
+ event: HTTPEvent;
141
+ error: any;
142
+ config: SessionConfigJWS<T, MaxAge>;
143
+ }) => void | Promise<void>;
101
144
  }
102
- interface SessionConfigJWS {
145
+ interface SessionConfigJWS<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined> {
103
146
  key: JWK_Symmetric | {
104
147
  privateKey: JWK_Private;
105
148
  publicKey: JWK_Public | JWK_Public[] | JWKSet;
106
149
  };
107
- maxAge?: number;
150
+ maxAge?: MaxAge;
108
151
  name?: string;
109
152
  cookie?: false | (CookieSerializeOptions & {
110
153
  chunkMaxLength?: number;
@@ -115,15 +158,14 @@ interface SessionConfigJWS {
115
158
  signOptions?: Omit<JWSSignOptions, "expiresIn">;
116
159
  verifyOptions?: JWTClaimValidationOptions;
117
160
  };
118
- hooks?: SessionHooksJWS;
161
+ hooks?: SessionHooksJWS<T, MaxAge>;
119
162
  }
120
- type SessionUpdate<T extends SessionDataT = SessionDataT> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
121
- declare function useJWSSession<T extends SessionDataT = SessionDataT>(event: HTTPEvent, config: SessionConfigJWS): Promise<SessionManager<T>>;
122
- declare function getJWSSession<T extends SessionDataT = SessionDataT>(event: HTTPEvent, config: SessionConfigJWS): Promise<SessionJWS<T>>;
123
- declare function updateJWSSession<T extends SessionDataT = SessionDataT>(event: HTTPEvent, config: SessionConfigJWS, update?: SessionUpdate<T>): Promise<SessionJWS<T>>;
124
- declare function signJWSSession<T extends SessionDataT = SessionDataT>(event: HTTPEvent, config: SessionConfigJWS): Promise<string>;
125
- declare function verifyJWSSession(_event: HTTPEvent, config: SessionConfigJWS, token: string): Promise<Partial<SessionJWS>>;
126
- declare function clearJWSSession(event: HTTPEvent, config: Partial<SessionConfigJWS>): Promise<void>;
163
+ declare function useJWSSession<T extends JWTClaims, MaxAge extends number | undefined>(event: HTTPEvent, config: SessionConfigJWS<T, MaxAge>): Promise<SessionManager<T, MaxAge>>;
164
+ declare function getJWSSession<T extends JWTClaims, MaxAge extends number | undefined>(event: HTTPEvent, config: SessionConfigJWS<T, MaxAge>): Promise<SessionJWS<T, MaxAge>>;
165
+ declare function updateJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: HTTPEvent, config: SessionConfigJWS<T, MaxAge>, update?: SessionUpdate<T>): Promise<SessionJWS<T, MaxAge>>;
166
+ declare function signJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: HTTPEvent, config: SessionConfigJWS<T, MaxAge>): Promise<string>;
167
+ declare function verifyJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(_event: HTTPEvent, config: SessionConfigJWS<T, MaxAge>, token: string): Promise<Partial<SessionJWS<T, MaxAge>>>;
168
+ declare function clearJWSSession<T extends JWTClaims = JWTClaims, MaxAge extends number | undefined = number | undefined>(event: HTTPEvent, config: Partial<SessionConfigJWS<T, MaxAge>>): Promise<void>;
127
169
 
128
170
  export { JWEEncryptOptions, JWKSet, JWK_Private, JWK_Public, JWK_Symmetric, JWTClaimValidationOptions, JWTClaims, clearJWESession, clearJWSSession, getJWESession, getJWSSession, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession };
129
- export type { SessionConfigJWE, SessionConfigJWS, SessionData, SessionHooksJWE, SessionHooksJWS, SessionJWE, SessionJWS, SessionManager };
171
+ export type { SessionConfigJWE, SessionConfigJWS, SessionData, SessionHooksJWE, SessionHooksJWS, SessionJWE, SessionJWS, SessionManager, SessionUpdate };
@@ -49,12 +49,22 @@ async function getJWESession(event, config) {
49
49
  if (existingSession) {
50
50
  const session2 = existingSession[kGetSessionPromise$1] ? await existingSession[kGetSessionPromise$1] : existingSession;
51
51
  if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && hasWritableResponse$1(event)) {
52
- await config.hooks?.onExpire?.(event, void 0, config);
52
+ await config.hooks?.onExpire?.({
53
+ event,
54
+ error: new Error(
55
+ `JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${new Date(session2.expiresAt * 1e3).toISOString()})`
56
+ ),
57
+ config
58
+ });
53
59
  return clearJWESession(event, config).then(
54
60
  () => getJWESession(event, config)
55
61
  );
56
62
  }
57
- await config.hooks?.onRead?.(session2, event, config);
63
+ await config.hooks?.onRead?.({
64
+ event,
65
+ session: session2,
66
+ config
67
+ });
58
68
  return session2;
59
69
  }
60
70
  const session = {
@@ -64,27 +74,35 @@ async function getJWESession(event, config) {
64
74
  data: new NullProtoObj()
65
75
  };
66
76
  context.sessions[sessionName] = session;
67
- let jweToken;
77
+ let token;
68
78
  if (config.sessionHeader !== false) {
69
79
  const headerName = typeof config.sessionHeader === "string" ? config.sessionHeader.toLowerCase() : `x-${sessionName.toLowerCase()}-session`;
70
80
  const headerValue = event.req.headers.get(headerName);
71
81
  if (typeof headerValue === "string") {
72
- jweToken = headerValue;
82
+ token = headerValue.startsWith("Bearer ") ? headerValue.slice(7).trim() : headerValue;
73
83
  }
74
84
  }
75
- if (!jweToken) {
76
- jweToken = getChunkedCookie(event, sessionName);
85
+ if (!token) {
86
+ token = getChunkedCookie(event, sessionName);
77
87
  }
78
- if (jweToken) {
79
- const promise = unsealJWESession(event, config, jweToken).catch(async (error_) => {
88
+ if (token) {
89
+ const promise = unsealJWESession(event, config, token).catch(async (error_) => {
80
90
  if (error_ instanceof Error) {
81
91
  const message = error_.message;
82
92
  if (message.includes("Token has expired") || message.includes("Token is too old")) {
83
- await config.hooks?.onExpire?.(event, error_, config);
93
+ await config.hooks?.onExpire?.({
94
+ event,
95
+ error: error_,
96
+ config
97
+ });
84
98
  return void 0;
85
99
  }
86
100
  }
87
- await config.hooks?.onError?.(event, error_, config);
101
+ await config.hooks?.onError?.({
102
+ event,
103
+ error: error_,
104
+ config
105
+ });
88
106
  return void 0;
89
107
  }).then((unsealed) => {
90
108
  if (unsealed) {
@@ -102,7 +120,11 @@ async function getJWESession(event, config) {
102
120
  session.expiresAt = config.maxAge ? session.createdAt + config.maxAge * 1e3 : void 0;
103
121
  await updateJWESession(event, config);
104
122
  }
105
- await config.hooks?.onRead?.(session, event, config);
123
+ await config.hooks?.onRead?.({
124
+ event,
125
+ session,
126
+ config
127
+ });
106
128
  return session;
107
129
  }
108
130
  async function updateJWESession(event, config, update) {
@@ -114,7 +136,11 @@ async function updateJWESession(event, config, update) {
114
136
  }
115
137
  if (update) {
116
138
  Object.assign(session.data, update);
117
- await config.hooks?.onUpdate?.(session, event, config);
139
+ await config.hooks?.onUpdate?.({
140
+ event,
141
+ session,
142
+ config
143
+ });
118
144
  }
119
145
  if (config.cookie !== false && hasWritableResponse$1(event)) {
120
146
  const sealed = await sealJWESession(event, config);
@@ -167,11 +193,11 @@ async function unsealJWESession(_event, config, sealed) {
167
193
  const { payload } = await decrypt(sealed, key, {
168
194
  ...config.jwe?.decryptOptions,
169
195
  requiredClaims: [
170
- ...config.jwe?.decryptOptions?.requiredClaims?.filter(
171
- (claim) => claim !== "jti" && claim !== "iat"
172
- ) || [],
173
- "jti",
174
- "iat"
196
+ .../* @__PURE__ */ new Set([
197
+ ...config.jwe?.decryptOptions?.requiredClaims || [],
198
+ "jti",
199
+ "iat"
200
+ ])
175
201
  ],
176
202
  maxTokenAge: config.maxAge,
177
203
  algorithms: alg ? [alg] : void 0,
@@ -207,7 +233,10 @@ async function clearJWESession(event, config) {
207
233
  expires: /* @__PURE__ */ new Date(0),
208
234
  maxAge: void 0
209
235
  });
210
- await config.hooks?.onClear?.(event, config);
236
+ await config.hooks?.onClear?.({
237
+ event,
238
+ config
239
+ });
211
240
  }
212
241
  }
213
242
  function getSessionFromContext$1(event, sessionName) {
@@ -304,12 +333,22 @@ async function getJWSSession(event, config) {
304
333
  if (existingSession) {
305
334
  const session2 = existingSession[kGetSessionPromise] ? await existingSession[kGetSessionPromise] : existingSession;
306
335
  if (session2.expiresAt !== void 0 && session2.expiresAt < Date.now() && hasWritableResponse(event)) {
307
- await config.hooks?.onExpire?.(event, void 0, config);
336
+ await config.hooks?.onExpire?.({
337
+ event,
338
+ error: new Error(
339
+ `JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${new Date(session2.expiresAt * 1e3).toISOString()})`
340
+ ),
341
+ config
342
+ });
308
343
  return clearJWSSession(event, config).then(
309
344
  () => getJWSSession(event, config)
310
345
  );
311
346
  }
312
- await config.hooks?.onRead?.(session2, event, config);
347
+ await config.hooks?.onRead?.({
348
+ event,
349
+ session: session2,
350
+ config
351
+ });
313
352
  return session2;
314
353
  }
315
354
  const session = {
@@ -324,7 +363,7 @@ async function getJWSSession(event, config) {
324
363
  const headerName = typeof config.sessionHeader === "string" ? config.sessionHeader.toLowerCase() : `x-${sessionName.toLowerCase()}-session`;
325
364
  const headerValue = event.req.headers.get(headerName);
326
365
  if (typeof headerValue === "string") {
327
- token = headerValue;
366
+ token = headerValue.startsWith("Bearer ") ? headerValue.slice(7).trim() : headerValue;
328
367
  }
329
368
  }
330
369
  if (!token) {
@@ -333,10 +372,18 @@ async function getJWSSession(event, config) {
333
372
  if (token) {
334
373
  const promise = verifyJWSSession(event, config, token).catch(async (error_) => {
335
374
  if (error_ instanceof Error && (error_.message.includes("Token has expired") || error_.message.includes("Token is too old"))) {
336
- await config.hooks?.onExpire?.(event, error_, config);
375
+ await config.hooks?.onExpire?.({
376
+ event,
377
+ error: error_,
378
+ config
379
+ });
337
380
  return void 0;
338
381
  }
339
- await config.hooks?.onError?.(event, error_, config);
382
+ await config.hooks?.onError?.({
383
+ event,
384
+ error: error_,
385
+ config
386
+ });
340
387
  return void 0;
341
388
  }).then((unsealed) => {
342
389
  if (unsealed) {
@@ -354,7 +401,11 @@ async function getJWSSession(event, config) {
354
401
  session.expiresAt = config.maxAge ? session.createdAt + config.maxAge * 1e3 : void 0;
355
402
  await updateJWSSession(event, config);
356
403
  }
357
- await config.hooks?.onRead?.(session, event, config);
404
+ await config.hooks?.onRead?.({
405
+ event,
406
+ session,
407
+ config
408
+ });
358
409
  return session;
359
410
  }
360
411
  async function updateJWSSession(event, config, update) {
@@ -366,7 +417,11 @@ async function updateJWSSession(event, config, update) {
366
417
  }
367
418
  if (update) {
368
419
  Object.assign(session.data, update);
369
- await config.hooks?.onUpdate?.(session, event, config);
420
+ await config.hooks?.onUpdate?.({
421
+ event,
422
+ session,
423
+ config
424
+ });
370
425
  }
371
426
  if (config.cookie !== false && hasWritableResponse(event)) {
372
427
  const token = await signJWSSession(event, config);
@@ -420,11 +475,11 @@ async function verifyJWSSession(_event, config, token) {
420
475
  const { payload } = await verify(token, jwk, {
421
476
  ...config.jws?.verifyOptions,
422
477
  requiredClaims: [
423
- ...config.jws?.verifyOptions?.requiredClaims?.filter(
424
- (claim) => claim !== "jti" && claim !== "iat"
425
- ) || [],
426
- "jti",
427
- "iat"
478
+ .../* @__PURE__ */ new Set([
479
+ ...config.jws?.verifyOptions?.requiredClaims || [],
480
+ "jti",
481
+ "iat"
482
+ ])
428
483
  ],
429
484
  typ: typ || "JWT",
430
485
  algorithms: alg ? [alg] : void 0,
@@ -455,7 +510,10 @@ async function clearJWSSession(event, config) {
455
510
  expires: /* @__PURE__ */ new Date(0),
456
511
  maxAge: void 0
457
512
  });
458
- await config.hooks?.onClear?.(event, config);
513
+ await config.hooks?.onClear?.({
514
+ event,
515
+ config
516
+ });
459
517
  }
460
518
  }
461
519
  function getSessionFromContext(event, sessionName) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unjwt",
3
- "version": "0.5.25",
3
+ "version": "0.5.27",
4
4
  "description": "Low-level JWT utilities",
5
5
  "repository": "sandros94/unjwt",
6
6
  "license": "MIT",
@@ -73,7 +73,7 @@
73
73
  "eslint": "^9.36.0",
74
74
  "eslint-config-unjs": "^0.5.0",
75
75
  "h3v1": "npm:h3@^1.15.4",
76
- "h3v2": "npm:h3@^2.0.1-rc.2",
76
+ "h3v2": "npm:h3@^2.0.1-rc.5",
77
77
  "jose": "^6.1.0",
78
78
  "prettier": "^3.6.2",
79
79
  "supertest": "^7.1.4",
@@ -83,8 +83,8 @@
83
83
  },
84
84
  "peerDependencies": {
85
85
  "cookie-es": "^1.2.2 || ^2.0.0",
86
- "h3": "^1.15.4 || >=2.0.1-rc.2 || ^2.0.1",
87
- "rou3": "^0.7.7"
86
+ "h3": "^1.15.4 || >=2.0.1-rc.5 || ^2.0.1",
87
+ "rou3": "^0.7.10"
88
88
  },
89
89
  "peerDependenciesMeta": {
90
90
  "cookie-es": {
@@ -92,7 +92,13 @@
92
92
  },
93
93
  "h3": {
94
94
  "optional": true
95
+ },
96
+ "rou3": {
97
+ "optional": true
95
98
  }
96
99
  },
97
- "packageManager": "pnpm@10.18.3"
100
+ "resolutions": {
101
+ "@eslint/plugin-kit": "^0.3.4"
102
+ },
103
+ "packageManager": "pnpm@10.19.0"
98
104
  }