unjwt 0.8.5 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +34 -21
  2. package/dist/_chunks/algorithms.mjs +44 -20
  3. package/dist/_chunks/digest.d.mts +4 -4
  4. package/dist/_chunks/digest.mjs +23 -15
  5. package/dist/_chunks/error.d.mts +29 -42
  6. package/dist/_chunks/export.mjs +1 -4
  7. package/dist/_chunks/index.d.mts +270 -234
  8. package/dist/_chunks/index2.d.mts +82 -189
  9. package/dist/_chunks/index4.d.mts +223 -60
  10. package/dist/_chunks/index5.d.mts +68 -31
  11. package/dist/_chunks/index6.d.mts +45 -64
  12. package/dist/_chunks/jwe.mjs +53 -48
  13. package/dist/_chunks/jwk.mjs +9 -3
  14. package/dist/_chunks/jws.mjs +55 -50
  15. package/dist/_chunks/jwt.d.mts +13 -49
  16. package/dist/_chunks/jwt.mjs +4 -158
  17. package/dist/_chunks/jwt2.mjs +162 -0
  18. package/dist/_chunks/libs/unsecure.d.mts +0 -6
  19. package/dist/_chunks/limits.d.mts +3 -2
  20. package/dist/_chunks/payload.mjs +13 -7
  21. package/dist/_chunks/wrap.mjs +3 -1
  22. package/dist/core/internal.d.mts +50 -2
  23. package/dist/core/internal.mjs +3 -1
  24. package/dist/core/jwe/index.d.mts +1 -1
  25. package/dist/core/jwk/index.d.mts +2 -2
  26. package/dist/core/jwk/index.mjs +2 -2
  27. package/dist/dpop/index.d.mts +77 -18
  28. package/dist/index.d.mts +6 -6
  29. package/dist/index.mjs +4 -4
  30. package/dist/session/index.d.mts +568 -22
  31. package/dist/session/index.mjs +1386 -34
  32. package/dist/utils/index.d.mts +4 -4
  33. package/dist/utils/index.mjs +2 -10
  34. package/package.json +4 -32
  35. package/dist/_chunks/codec-jwe.d.mts +0 -280
  36. package/dist/_chunks/codec-jws.mjs +0 -1005
  37. package/dist/_chunks/cookie-attributes.d.mts +0 -12
  38. package/dist/_chunks/cookie.mjs +0 -50
  39. package/dist/adapters/elysia/index.d.mts +0 -123
  40. package/dist/adapters/elysia/index.mjs +0 -120
  41. package/dist/adapters/h3/index.d.mts +0 -135
  42. package/dist/adapters/h3/index.mjs +0 -117
  43. package/dist/adapters/h3v1/index.d.mts +0 -148
  44. package/dist/adapters/h3v1/index.mjs +0 -128
@@ -1,44 +1,590 @@
1
- import { CookieJar, JWESessionConfig, JWESessionHooks, JWSSessionConfig, JWSSessionHooks, OpenedSessionState, SessionClaims, SessionData, SessionDecryptOptions, SessionDefinition, SessionDriver, SessionEncryptOptions, SessionHandedToken, SessionIssueOptions, SessionManager, SessionRecord, SessionRequestEvent, SessionSignOptions, SessionState, SessionUpdate, SessionUpdateTrigger, SessionVerifyOptions, WebSessionEvent } from "../_chunks/codec-jwe.mjs";
2
- import { CookieAttributes } from "../_chunks/cookie-attributes.mjs";
3
- import { CompositeKey, ContentEncryptionAlgorithm, DeriveJWKOptions, DeriveJWKReturn, DeriveKeyOptions, DeriveKeyReturn, Duration, ECDHEphemeralKeyInput, ExpiresIn, GenerateJWKOptions, GenerateJWKReturn, GenerateKeyAlgorithm, GenerateKeyOptions, GenerateKeyReturn, GeneratedJWKMap, GeneratedKeyMap, ImportedKey, ImportedKeyMap, ImportedPEMJWK, JOSEConsumerOptions, JOSELimits, JOSEPayload, JOSEPayloadMode, JOSEPayloadTypeMap, JWEAsymmetricPrivateJWK, JWEAsymmetricPublicJWK, JWEDecryptJWK, JWEDecryptOptions, JWEDecryptResult, JWEEncryptJWK, JWEEncryptOptions, JWEFlattenedSerialization, JWEGeneralRecipient, JWEGeneralSerialization, JWEHeaderParameters, JWEKeyLookup, JWEKeyManagementHeaderParameters, JWELibraryHeaderName, JWEMultiDecryptKey, JWEMultiDecryptOptions, JWEMultiDecryptResult, JWEMultiEncryptOptions, JWEMultiRecipient, JWEProtectedHeader, JWK, JWKAlgorithm, JWKCacheAdapter, JWKLookupFunction, JWKLookupFunctionHeader, JWKMetadata, JWKPEMAlgorithm, JWKParameters, JWKSet, JWK_AES_Algorithm, JWK_AES_CBC_HMAC, JWK_AES_GCM, JWK_AES_GCM_KW, JWK_AES_KW, JWK_Asymmetric, JWK_Asymmetric_Algorithm, JWK_EC, JWK_ECDH_ES, JWK_ECDSA, JWK_EC_Private, JWK_EC_Public, JWK_HMAC, JWK_OKP, JWK_OKP_Private, JWK_OKP_Public, JWK_OKP_SIGN, JWK_PBES2, JWK_Pair, JWK_Private, JWK_Public, JWK_RSA, JWK_RSA_ENC, JWK_RSA_PSS, JWK_RSA_Private, JWK_RSA_Public, JWK_RSA_SIGN, JWK_Symmetric, JWK_Symmetric_Algorithm, JWK_oct, JWSAlgorithm, JWSAsymmetricPrivateJWK, JWSAsymmetricPublicJWK, JWSFlattenedSerialization, JWSGeneralSerialization, JWSGeneralSignature, JWSHashedAlgorithm, JWSHeaderParameters, JWSKeyLookup, JWSMultiSignOptions, JWSMultiSigner, JWSMultiVerifyAllOptions, JWSMultiVerifyOptions, JWSMultiVerifyOutcome, JWSMultiVerifyResult, JWSProtectedHeader, JWSSignJWK, JWSSignOptions, JWSVerifyJWK, JWSVerifyOptions, JWSVerifyResult, JWT, JWTClaimValidationOptions, JWTClaims, JWTConfirmation, JWTTimeClaimOptions, JoseHeaderParameters, KeyManagementAlgorithm, KeyWrapAlgorithmOf, KeyWrappingAlgorithm, MaxTokenAge, NotBeforeIn, PEMType, PayloadOf, ToPublicJWKReturn, UnwrapKeyOptions, UnwrapKeyResult, UnwrappingKeyFor, WrapKeyOptions, WrapKeyResult, WrappingKeyFor } from "../_chunks/index.mjs";
4
- import { deriveJWKFromPassword, exportPEM, generateJWK, importPEM, toPublicJWK } from "../_chunks/index2.mjs";
1
+ import { JWTError } from "../_chunks/error.mjs";
2
+ import { CompositeKey, ContentEncryptionAlgorithm, DeriveJWKOptions, DeriveJWKReturn, DeriveKeyOptions, DeriveKeyReturn, Duration, ECDHEphemeralKeyInput, ExpiresIn, GenerateJWKOptions, GenerateJWKReturn, GenerateKeyAlgorithm, GenerateKeyOptions, GenerateKeyReturn, GeneratedJWKMap, GeneratedKeyMap, ImportedKey, ImportedKeyMap, ImportedPEMJWK, JOSEConsumerOptions, JOSELimits, JOSEPayload, JOSEPayloadMode, JOSEPayloadTypeMap, JWEAsymmetricPrivateJWK, JWEAsymmetricPublicJWK, JWEDecryptJWK, JWEDecryptOptions, JWEDecryptResult, JWEEncryptJWK, JWEEncryptOptions, JWEFlattenedSerialization, JWEGeneralRecipient, JWEGeneralSerialization, JWEHeaderParameters, JWEKeyLookup, JWEKeyManagementHeaderParameters, JWELibraryHeaderName, JWEMultiDecryptKey, JWEMultiDecryptOptions, JWEMultiDecryptResult, JWEMultiEncryptOptions, JWEMultiRecipient, JWEProtectedHeader, JWK, JWKAlgorithm, JWKCacheAdapter, JWKLookupFunction, JWKLookupFunctionHeader, JWKMetadata, JWKPEMAlgorithm, JWKParameters, JWKSet, JWK_AES_Algorithm, JWK_AES_CBC_HMAC, JWK_AES_GCM, JWK_AES_GCM_KW, JWK_AES_KW, JWK_Asymmetric, JWK_Asymmetric_Algorithm, JWK_EC, JWK_ECDH_ES, JWK_ECDSA, JWK_EC_Private, JWK_EC_Public, JWK_HMAC, JWK_OKP, JWK_OKP_Private, JWK_OKP_Public, JWK_OKP_SIGN, JWK_PBES2, JWK_Pair, JWK_Private, JWK_Public, JWK_RSA, JWK_RSA_ENC, JWK_RSA_PSS, JWK_RSA_Private, JWK_RSA_Public, JWK_RSA_SIGN, JWK_Symmetric, JWK_Symmetric_Algorithm, JWK_oct, JWSAlgorithm, JWSAsymmetricPrivateJWK, JWSAsymmetricPublicJWK, JWSFlattenedSerialization, JWSGeneralSerialization, JWSGeneralSignature, JWSHashedAlgorithm, JWSHeaderParameters, JWSKeyLookup, JWSMultiSignOptions, JWSMultiSigner, JWSMultiVerifyAllOptions, JWSMultiVerifyOptions, JWSMultiVerifyOutcome, JWSMultiVerifyResult, JWSProtectedHeader, JWSSignJWK, JWSSignOptions, JWSVerifyJWK, JWSVerifyOptions, JWSVerifyResult, JWT, JWTClaimValidationOptions, JWTClaims, JWTConfirmation, JWTTimeClaimOptions, JoseHeaderParameters, KeyManagementAlgorithm, KeyWrapAlgorithmOf, KeyWrappingAlgorithm, MaxTokenAge, NotBeforeIn, PEMType, PayloadOf, StrictOmit, ToPublicJWKReturn, UnwrapKeyOptions, UnwrapKeyResult, UnwrappingKeyFor, WrapKeyOptions, WrapKeyResult, WrappingKeyFor } from "../_chunks/index.mjs";
5
3
  import { thumbprint } from "../_chunks/index3.mjs";
6
- /** Session state for the current request, mirroring the claims of its JWS token. */
4
+ import { deriveJWKFromPassword, exportPEM, generateJWK, importPEM, toPublicJWK } from "../_chunks/index4.mjs";
5
+ /** The shape session data must match. Its `any` values let an `interface` without an index signature match it. */
6
+ type SessionRecord = Record<string, any>;
7
+ /** The default session data: JWT claims, with `jti` and `iat` always set. */
8
+ interface SessionClaims extends Required<Pick<JWTClaims, "jti" | "iat">>, StrictOmit<JWTClaims, "jti" | "iat"> {}
9
+ /** Session data without `jti`, `iat`, `exp` and `nbf`, which the session sets on every issue. */
10
+ type SessionData<T extends SessionRecord = SessionClaims> = StrictOmit<T, "jti" | "iat" | "exp" | "nbf">;
11
+ /**
12
+ * Where the session's token comes from on this request, decided before it is opened:
13
+ * - `"cookie"`: the session cookie, also when the session header holds the very token of that cookie.
14
+ * - `"header"`: the session header, when it holds any other token or the session has no cookie.
15
+ * - `"token"`: a token in hand (`{ token }`), or a token passed to `open()`.
16
+ */
17
+ type SessionSource = "cookie" | "header" | "token";
18
+ /** Why `onUpdate` ran: an `update()` call, or `rolling` reissuing a session that was read. */
19
+ type SessionUpdateTrigger = "update" | "rolling";
20
+ /** What `update()` merges: a partial data object, or a function of the current data that returns one or `undefined`. */
21
+ type SessionUpdate<T extends SessionRecord = SessionClaims> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
22
+ /** The session of one request. Its getters read the current state of that request. */
23
+ interface SessionManager<T extends SessionRecord = SessionClaims, ConfigMaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
24
+ /** Session ID (`jti`), `undefined` until a token is read or issued. */
25
+ readonly id: string | undefined;
26
+ /** Issue time in ms, from `iat`. A session without a token holds the time it was created. */
27
+ readonly createdAt: number;
28
+ /** Expiry in ms: `exp`, or `iat + maxAge` when sooner. Always a number when the session has a `maxAge`. */
29
+ readonly expiresAt: ConfigMaxAge extends ExpiresIn ? number : number | undefined;
30
+ /** Session data, without `jti`, `iat`, `exp` and `nbf`. */
31
+ readonly data: SessionData<T>;
32
+ /**
33
+ * The session's token: the one behind its current state, read and opened on this request or issued by `update()`. `undefined` when there is none,
34
+ * when the read failed, and after `clear()`. The token the request carries, whatever its read made of it, is the definition's `token(event)`.
35
+ * On a `"cookie"` session, a token `update()` issues is also written to the cookie. On a `"header"` or `"token"` session it is here alone, and reaches the client only if you send it.
36
+ */
37
+ readonly token: string | undefined;
38
+ /**
39
+ * Where the token of this request comes from, which decides what `update()` and `clear()` reach. It holds for the whole request.
40
+ * - `"cookie"`: `update()` writes the new token to the cookie, and `clear()` expires it.
41
+ * - `"header"` or `"token"`: `update()` re-mints onto `token` and writes nothing, and `clear()` empties the session for this request alone. The client keeps the token it sent, valid until it expires.
42
+ */
43
+ readonly source: SessionSource;
44
+ /**
45
+ * The error the read of this request ended with, the same object its hook received. `undefined` when the request carries no token, when the read
46
+ * succeeded, and after `update()` or `clear()`. Later `use()` calls on the same request return it too.
47
+ * - `ERR_JWT_EXPIRED`: the token is expired, the error `onExpire` received.
48
+ * - `ERR_SESSION_TOKEN_INVALID`: the token failed its checks, the error `onError` received.
49
+ * - `ERR_SESSION_READ_FAILED`: the key lookup threw or returned a key that cannot be used, the error `onError` received.
50
+ *
51
+ * A request without a token is the definition's `token(event)` returning `undefined`. A read that succeeded sets `id`.
52
+ */
53
+ readonly error: JWTError | undefined;
54
+ /**
55
+ * Merges `update` into the data and issues a token with a fresh `jti` and `iat`. `options.maxAge` overrides the config's `maxAge` for this token.
56
+ * A `"cookie"` session writes the token to the response's cookie. A `"header"` or `"token"` session writes nothing: the token is on `token` alone, for you to send. Later requests read the data back through JSON.
57
+ * If issuing or the cookie write fails, the session is restored, `onError` runs and the call rejects. A throwing `onUpdate` rejects the call and keeps the new session.
58
+ * @throws `ERR_SESSION_READONLY_EVENT` if a `"cookie"` session has no response, or the response was already sent.
59
+ * @throws `ERR_INVALID_OPTION` if the update is not a plain object or holds `__proto__`, `constructor` or `prototype`.
60
+ * @throws `ERR_SESSION_CONFIG_INVALID` if a `"cookie"` session's token needs more than 16 cookie chunks.
61
+ */
62
+ update: (update?: SessionUpdate<T>, options?: SessionIssueOptions) => Promise<SessionManager<T, ConfigMaxAge>>;
63
+ /**
64
+ * Empties the session for the rest of the request and runs `onClear`.
65
+ * A `"cookie"` session with a response expires its cookie. A `"header"` or `"token"` session writes nothing: the client keeps the token it sent, valid until it expires.
66
+ * @throws `ERR_SESSION_READONLY_EVENT` if a `"cookie"` session's response was already sent.
67
+ */
68
+ clear: () => Promise<SessionManager<T, ConfigMaxAge>>;
69
+ }
70
+ /** The config members every session shares, whether it signs or encrypts its token. */
71
+ interface SessionBaseConfig<MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
72
+ /** Session lifetime: each token gets `exp = iat + maxAge` and its cookie expires then. An incoming token must have `exp` and ends at `exp` or `iat + maxAge`, whichever is sooner. @default undefined (never expires) */
73
+ maxAge?: MaxAge;
74
+ /**
75
+ * Reissues a session read from its cookie. Requires `maxAge`.
76
+ * - `true`: every read reissues.
77
+ * - a duration, shorter than `maxAge`: a read reissues once the token is at least that old. With `maxAge: "1h"` and
78
+ * `rolling: "15m"`, reads in the first 15 minutes change nothing, and the first read after that issues a fresh hour.
79
+ *
80
+ * A read that cannot write the cookie (no response, or a response already sent) does not reissue. The next request, which sends the same token, does.
81
+ * A session read from the session header or from a token in hand never reissues: its token stays the one the client sent.
82
+ * @default undefined (the session expires at `iat + maxAge` however often it is read)
83
+ */
84
+ rolling?: true | ExpiresIn;
85
+ /** Cookie name, also the base of the default session header. A valid cookie name without a trailing `.<digits>`. `__Host-` and `__Secure-` names get their prefix rules checked. */
86
+ name?: string;
87
+ /**
88
+ * Request header to read a bare or `Bearer` token from: a header name, `true` for `x-<name>-session` (without a `__Host-` or `__Secure-` prefix), or `false` for none.
89
+ * A request that sends it is read from it alone and its cookie is left as it is, unless the header holds the very token of the request's session cookie: that request is a cookie session.
90
+ * A value that is not a token runs `onError`.
91
+ * With no header read and `cookie: false`, the session has no token source and reading it throws `ERR_SESSION_CONFIG_INVALID`. @default undefined (no header is read)
92
+ */
93
+ sessionHeader?: boolean | string;
94
+ /** Session ID (`jti`) generator. @default crypto.randomUUID */
95
+ generateId?: () => string;
96
+ }
97
+ /** Lifecycle hooks. `onRead`, `onExpire` and `onError` are mutually exclusive per token. `session` is the live manager, open to `update()` and `clear()`. `oldSession` is a snapshot. */
98
+ interface SessionHooks<TSession, TManager, TArgs extends Record<string, unknown>, TConfig> {
99
+ /** Runs once per request, after a token is read and verified. A throw empties the session and rejects the read. */
100
+ onRead?: (args: TArgs & {
101
+ session: TManager & {
102
+ id: string;
103
+ token: string;
104
+ };
105
+ config: TConfig;
106
+ }) => void | Promise<void>;
107
+ /** Runs after `update()` or `rolling` issues a token and, on a cookie session, writes its cookie. A throw rejects the call and keeps the new session. */
108
+ onUpdate?: (args: TArgs & {
109
+ session: TManager & {
110
+ id: string;
111
+ token: string;
112
+ };
113
+ /** The session before the update, its data deep-copied. */
114
+ oldSession: TSession;
115
+ trigger: SessionUpdateTrigger;
116
+ config: TConfig;
117
+ }) => void | Promise<void>;
118
+ /** Runs when `clear()` empties the session. `oldSession` is `undefined` when the session had no `id`, no token and no `error`. */
119
+ onClear?: (args: TArgs & {
120
+ oldSession: TSession | undefined;
121
+ config: TConfig;
122
+ }) => void | Promise<void>;
123
+ /** Runs when the incoming token is expired, with its decoded claims and the `ERR_JWT_EXPIRED` error. The session is empty after it. */
124
+ onExpire?: (args: TArgs & {
125
+ session: {
126
+ id: string | undefined;
127
+ createdAt: number | undefined;
128
+ expiresAt: number | undefined;
129
+ token: string;
130
+ /** Where the expired token came from. */
131
+ source: SessionSource;
132
+ };
133
+ error: JWTError;
134
+ config: TConfig;
135
+ }) => void | Promise<void>;
136
+ /**
137
+ * Runs when a token fails to open for a reason other than expiry, and when an issue or cookie write fails. The session is empty after a read.
138
+ * - `ERR_SESSION_TOKEN_INVALID`: the token failed its checks, or `onKeyLookup` found no key for it. Its cookie is expired.
139
+ * - `ERR_SESSION_READ_FAILED`: `onKeyLookup` threw, its error as `cause`, or returned a key that cannot be used, an `ERR_JWK_INVALID` as `cause`. The cookie is kept, and `clear()` expires it.
140
+ */
141
+ onError?: (args: TArgs & {
142
+ session: TManager;
143
+ error: any;
144
+ config: TConfig;
145
+ }) => void | Promise<void>;
146
+ }
147
+ /** Overrides for one `update()` or `issue()` call. */
148
+ interface SessionIssueOptions {
149
+ /** Lifetime of this token, in place of the config's `maxAge`. A read under the config's `maxAge` still ends the session at `iat + maxAge`. */
150
+ maxAge?: ExpiresIn;
151
+ }
152
+ /** Session state for the current request, from the claims of its token. */
153
+ interface SessionState<T extends SessionRecord, MaxAge extends ExpiresIn | undefined> {
154
+ /** Session ID (`jti`), `undefined` until a token is read or issued. */
155
+ id: string | undefined;
156
+ /** Issue time in ms, from the `iat` claim in seconds. */
157
+ createdAt: number;
158
+ /** Expiry in ms, from the `exp` claim in seconds, or `iat + maxAge` when sooner. */
159
+ expiresAt: MaxAge extends ExpiresIn ? number : number | undefined;
160
+ data: SessionData<T>;
161
+ token: string | undefined;
162
+ /** Where the token of this request comes from. */
163
+ source: SessionSource;
164
+ /** The error the read of this request ended with, `ERR_JWT_EXPIRED`, `ERR_SESSION_TOKEN_INVALID` or `ERR_SESSION_READ_FAILED`, the object its hook received. `undefined` when the request carries no token, when the read succeeded, and after `update()` or `clear()`. */
165
+ error: JWTError | undefined;
166
+ }
167
+ /** Session state that `open()` reads from a token: `id` and `createdAt` are always set, and `source` is `"token"`. */
168
+ type OpenedSessionState<T extends SessionRecord, MaxAge extends ExpiresIn | undefined> = Pick<SessionState<T, MaxAge>, "id" | "createdAt" | "expiresAt" | "data" | "source"> & {
169
+ id: string;
170
+ createdAt: number;
171
+ };
172
+ /** One session, defined once from its config and used on any request. */
173
+ interface SessionDefinition<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> {
174
+ /**
175
+ * Reads the request's session and returns its manager. Later calls on the same request share that state.
176
+ * @throws `ERR_SESSION_CONFIG_INVALID` if the session has no token source, or a session of the other family uses its name on this request.
177
+ * @throws `ERR_SESSION_KEY_INVALID` if a configured key fails to import.
178
+ */
179
+ use: (event: TEvent) => Promise<SessionManager<T, MaxAge>>;
180
+ /**
181
+ * Returns the transport's token, unopened: the one the request carries (a handed token, the session header when it is present and differs from
182
+ * the cookie, otherwise the cookie) whatever `use()` made of it, or the one `update()` issued on this request. `undefined` when the request
183
+ * carries none, and after `clear()`. A failed read leaves it as sent, so a caller can forward or log it and tell no token from one that could
184
+ * not be checked. The token behind the session's state, `undefined` once a read fails, is the manager's `token`.
185
+ */
186
+ token: (event: TEvent) => string | undefined;
187
+ /** Returns a token for `data` with a fresh `jti` and `iat`, and `exp` from `maxAge` (`options.maxAge` overrides it). Reads and writes no request. @throws `ERR_INVALID_OPTION` if `data` is not a plain object or holds `__proto__`, `constructor` or `prototype`. */
188
+ issue: (data?: Partial<SessionData<T>>, options?: SessionIssueOptions) => Promise<string>;
189
+ /**
190
+ * Opens a token into session state. Checks `typ`, the algorithms the keys serve, `jti`, `iat`, and `exp` when `maxAge` is set. The key lookup hook receives no event.
191
+ * @throws `ERR_JWT_EXPIRED` if the token is expired.
192
+ * @throws `ERR_SESSION_TOKEN_INVALID` if the token fails any other check.
193
+ * @throws `ERR_SESSION_READ_FAILED` if the key lookup hook throws or returns a key that cannot be used.
194
+ */
195
+ open: (token: string) => Promise<OpenedSessionState<T, MaxAge>>;
196
+ }
197
+ interface SessionRequestBase {
198
+ /** The response being prepared. Without it the session is read-only. Each cookie write is copied to `errHeaders` too: h3 and Nitro send only these for a thrown handler. */
199
+ readonly res?: {
200
+ readonly headers: Headers;
201
+ readonly errHeaders?: Headers;
202
+ };
203
+ /** Per-request state shared with the framework. Sessions are stored in its `unjwt` member. Without it, state is keyed on `req`, else on the event. */
204
+ readonly context?: Record<string, unknown>;
205
+ }
206
+ /** A request event, by its `Request` or by its `Headers` (a `Request` itself, a WebSocket upgrade request). `req` is read first. */
207
+ type SessionRequestEvent = SessionRequestBase & ({
208
+ readonly req: Request;
209
+ readonly headers?: Headers;
210
+ } | {
211
+ readonly headers: Headers;
212
+ readonly req?: Request;
213
+ });
214
+ /** A token passed in directly. `update()` issues onto `session.token`, and sending it is the caller's job. */
215
+ interface SessionHandedToken {
216
+ token: string | undefined;
217
+ }
218
+ /** What the Web session driver accepts: a request event, or a token in hand. Any other shape throws `ERR_SESSION_CONFIG_INVALID`. */
219
+ type WebSessionEvent = SessionRequestEvent | SessionHandedToken;
220
+ /**
221
+ * A symmetric key that signs and verifies, an HMAC `oct` JWK or a secret `CryptoKey`, a JWK Set of HMAC `oct` JWKs, or a pair:
222
+ * `privateKey` signs and `publicKey` (a JWK, a JWK list, a JWK Set or a `CryptoKey`) verifies. A key without `alg` (a `CryptoKey`, an
223
+ * `oct` JWK without `alg`) requires a pinned `jws.signOptions.alg`, unless it is the half of a pair whose other half names one, which it
224
+ * then must carry. A pair's single `publicKey` that names an algorithm names the one `privateKey` signs with, and a list or JWK Set
225
+ * holds at least one key that serves it, beside keys of other algorithms. A JWK Set's first key signs and every key verifies, each checked as a lone key, the pin naming the first alone; a
226
+ * token of a key without `kid` may meet at most `jws.verifyOptions.limits.keyCandidates` keys, those whose `alg` serves it and those
227
+ * without `alg`. A lone asymmetric key throws `ERR_SESSION_KEY_INVALID`: it signs with one half and verifies with the other, so pass
228
+ * both as a pair.
229
+ */
230
+ type JWSSessionKey = CryptoKey | JWK_oct<JWK_HMAC> | JWKSet<JWK_oct<JWK_HMAC>[]> | {
231
+ privateKey: JWSAsymmetricPrivateJWK | CryptoKey;
232
+ publicKey: JWSAsymmetricPublicJWK | JWSAsymmetricPublicJWK[] | JWKSet | CryptoKey;
233
+ };
234
+ interface ExpirableCookieAttributes {
235
+ expires?: Date;
236
+ maxAge?: number;
237
+ }
238
+ /** The cookies of one request and its response, as a framework exposes them. */
239
+ interface CookieJar<A extends ExpirableCookieAttributes = ExpirableCookieAttributes> {
240
+ /** Returns the request's cookie `name`. */
241
+ read(name: string): string | undefined;
242
+ /** Returns the value this response already set for `name` (`""` once deleted). Implement it when the framework exposes response cookies. */
243
+ written?(name: string): string | undefined;
244
+ /** Sets a response cookie. Omit it when the event cannot send a `Set-Cookie` (a request without a response): a cookie session is then read-only. */
245
+ write?(name: string, value: string, attrs: A): void;
246
+ }
247
+ /** What a framework driver implements. The session reads its token and writes its cookie through these members. */
248
+ interface SessionDriver<TEvent> {
249
+ /** Starts the message of every error the session throws. */
250
+ prefix: string;
251
+ /** Returns a record unique to the request, where session state and the name registry are stored. */
252
+ state(event: TEvent): Record<string, unknown>;
253
+ /** Returns a request header by lowercase name. */
254
+ header(event: TEvent, name: string): string | null | undefined;
255
+ /** Returns the cookie jar of the request and its response. */
256
+ cookies(event: TEvent): CookieJar;
257
+ /** Returns `false` once the response was sent (Node `headersSent`): `update()` and `clear()` then throw `ERR_SESSION_READONLY_EVENT`. Omitted, the response stays writable. */
258
+ writable?(event: TEvent): boolean;
259
+ /** Returns `{ token }` when the event holds the token itself. No cookie or header is read then, and the session's source is `"token"`. */
260
+ handed?(event: TEvent): {
261
+ token: string | undefined;
262
+ } | undefined;
263
+ }
264
+ /** The `Set-Cookie` attributes of a session cookie (RFC 6265, RFC 6265bis, and CHIPS: Cookies Having Independent Partitioned State). */
265
+ interface CookieAttributes {
266
+ /** `Domain`. A `__Host-` name refuses it. */
267
+ domain?: string;
268
+ /** `Expires`. An issued token with an `exp` sets it to that time. */
269
+ expires?: Date;
270
+ /** `HttpOnly`: page scripts cannot read the cookie. */
271
+ httpOnly?: boolean;
272
+ /** `Max-Age` in seconds. An issued token with an `exp` replaces it with `expires`. */
273
+ maxAge?: number;
274
+ /** `Path`. A `__Host-` name requires `"/"`. */
275
+ path?: string;
276
+ /** `Priority`. */
277
+ priority?: "low" | "medium" | "high";
278
+ /** `SameSite`. `true` is `Strict`, and `"none"` requires `secure`. */
279
+ sameSite?: boolean | "lax" | "strict" | "none";
280
+ /** `Secure`. A `__Host-` or `__Secure-` name requires it. */
281
+ secure?: boolean;
282
+ /** `Partitioned` (CHIPS). Requires `secure`. */
283
+ partitioned?: boolean;
284
+ }
285
+ /** The attributes a session cookie gets unless its config sets them: `path` `"/"`, `secure`, `httpOnly` and `sameSite` `"lax"`. */
286
+ export declare const DEFAULT_SESSION_COOKIE: Readonly<CookieAttributes>;
287
+ /** The token sources of one session, and the attributes its cookie is written with. */
288
+ interface SessionTransportOptions {
289
+ /** Session name: the cookie name, and the base of the default session header. */
290
+ name: string;
291
+ /** Request header to read the token from, before the cookie: a name, or `true` for `x-<name>-session`. Unset or `false` reads no header. */
292
+ sessionHeader?: boolean | string;
293
+ /** The cookie's attributes and the chunk size its token is split at (`4000` when unset), or `false` for no cookie. */
294
+ cookie: false | {
295
+ attrs: CookieAttributes;
296
+ chunkMaxLength?: number;
297
+ };
298
+ }
299
+ /** How one session reads its token from the request and writes it to the response. */
300
+ interface SessionTransport {
301
+ /** Where the token is read from: the driver's token in hand, the session header, or the cookie. Only a cookie is written back. */
302
+ source: SessionSource;
303
+ /** The token in hand, else the session header's, else the cookie this response wrote, else the request's. Absent without a token source. */
304
+ read?: () => string | undefined;
305
+ /** The session header the request sent, by its lowercase name, when it holds neither a bare token nor `Bearer <token>`. The session decides how to report it. */
306
+ malformed?: {
307
+ header: string;
308
+ };
309
+ /**
310
+ * Writes the token to the cookie, split into chunks past `chunkMaxLength`, and returns `true`. With `expiresAt` (ms), the cookie gets that `expires` and no
311
+ * `maxAge`, which would take precedence (RFC 6265 §5.3). Once the response was sent, writes nothing and returns `false`.
312
+ * Present when the session reads its token from a cookie the event can write.
313
+ * @throws `ERR_SESSION_CONFIG_INVALID` if the token needs more than 16 cookie chunks.
314
+ */
315
+ write?: (token: string, options?: {
316
+ expiresAt?: number;
317
+ }) => boolean;
318
+ /**
319
+ * Expires the cookie and every chunk, and returns `true`. Once the response was sent, writes nothing and returns `false`.
320
+ * Present when the session reads its token from a cookie the event can write.
321
+ */
322
+ drop?: () => boolean;
323
+ /** The session reads its token from a cookie, but the event cannot write one (a request without a response). */
324
+ readonly: boolean;
325
+ /** Whether the response can still change. `false` once it was sent. */
326
+ writable: () => boolean;
327
+ }
328
+ /**
329
+ * Resolves the transport of one request, before any token is opened: a token the driver hands in, else the session header the request sends, else the cookie.
330
+ * A header that holds the very token of the request's cookie is the cookie. Any other header is read alone, the cookie left as it is.
331
+ * A token in hand or a header token is reissued onto the session only. Only a cookie session writes back.
332
+ */
333
+ export declare function resolveSessionTransport<TEvent>(driver: SessionDriver<TEvent>, event: TEvent, options: SessionTransportOptions): SessionTransport;
334
+ /** Throws `ERR_SESSION_CONFIG_INVALID` for a transport without a reader: the session has no token source to read or clear. */
335
+ export declare function assertSessionTokenSource(transport: SessionTransport, options: {
336
+ prefix: string;
337
+ }): asserts transport is SessionTransport & {
338
+ read: () => string | undefined;
339
+ };
340
+ /** Throws `ERR_SESSION_READONLY_EVENT` on an update when a cookie session cannot write its cookie, and on an update or clear once the response was sent. */
341
+ export declare function assertSessionWritable(transport: SessionTransport, options: {
342
+ operation: "update" | "clear";
343
+ prefix: string;
344
+ }): void;
345
+ /** Refuses a `sessionHeader` that is neither a boolean nor a header name (RFC 7230 §3.2). */
346
+ export declare function assertSessionHeader(header: unknown, options: {
347
+ prefix: string;
348
+ }): void;
349
+ /**
350
+ * JWS verify options a session accepts. `algorithms` names the `alg` values a key without its own `alg` (a `CryptoKey`, an `oct` or RSA JWK
351
+ * without `alg`) verifies, and with `onKeyLookup` set, may also name those only the keys it returns serve. The session sets `typ`,
352
+ * `maxTokenAge`, `validateClaims` and `payload` itself.
353
+ */
354
+ type SessionVerifyOptions = StrictOmit<JWSVerifyOptions, "typ" | "maxTokenAge" | "validateClaims" | "payload">;
355
+ /** JWS sign options a session accepts. The session sets `exp` from `maxAge` and never sets `nbf`. */
356
+ type SessionSignOptions = StrictOmit<JWSSignOptions, "expiresIn" | "expiresAt" | "notBeforeIn" | "notBeforeAt">;
357
+ /** The JWS options of a session: `signOptions` for each issued token, `verifyOptions` for each incoming one. */
358
+ interface JWSSessionOptions {
359
+ signOptions?: SessionSignOptions;
360
+ verifyOptions?: SessionVerifyOptions;
361
+ }
362
+ /** The config of a JWS session, without its hooks. */
363
+ interface JWSSessionConfig<MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TCookie extends object = object> extends SessionBaseConfig<MaxAge> {
364
+ /** The key, or JWK Set, that signs and verifies the token. See {@link JWSSessionKey}. */
365
+ key: JWSSessionKey;
366
+ /** Cookie attributes, or `false` for no cookie. `chunkMaxLength` is the size the token is split at (`4000` when unset). `httpOnly: false` lets page scripts read the signed payload. @default { path: "/", secure: true, httpOnly: true, sameSite: "lax" } */
367
+ cookie?: false | (TCookie & {
368
+ chunkMaxLength?: number;
369
+ });
370
+ /**
371
+ * `signOptions.alg` is what each token is signed with, and names the algorithm of a key without its own `alg`, both halves of a pair
372
+ * included when neither names one: a half without one takes the `alg` its other half names. Verification accepts every `alg` the keys
373
+ * serve: a JWK's own `alg` (or an EC or OKP JWK's curve), and for a key without one, the pin and each algorithm of
374
+ * `verifyOptions.algorithms` its material carries. An empty `verifyOptions.algorithms`, or one listing an algorithm no key serves,
375
+ * throws `ERR_SESSION_CONFIG_INVALID`, unless `onKeyLookup` is set for the latter.
376
+ * `signOptions.protectedHeader.typ` defaults to `"session+jwt"` (RFC 8725 §3.11).
377
+ */
378
+ jws?: JWSSessionOptions;
379
+ }
380
+ /** Session state for the current request, from the claims of its JWS token. */
7
381
  interface SessionJWS<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> extends SessionState<T, MaxAge> {}
8
- /** JWS session hooks; `onRead`, `onExpire` and `onError` are mutually exclusive per token. */
9
- interface SessionHooksJWS<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> extends JWSSessionHooks<SessionJWS<T, MaxAge>, SessionManager<T, MaxAge>, {
382
+ /** JWS session hooks. `onRead`, `onExpire` and `onError` are mutually exclusive per token. */
383
+ interface SessionHooksJWS<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> extends SessionHooks<SessionJWS<T, MaxAge>, SessionManager<T, MaxAge>, {
10
384
  event: TEvent;
11
- }, SessionConfigJWS<T, MaxAge, TEvent>> {}
12
- /** Configuration for a JWS-backed (signed, not encrypted) session. */
385
+ }, SessionConfigJWS<T, MaxAge, TEvent>> {
386
+ /** Returns the key that verifies an incoming token. See {@link JWSSessionKeyLookup}. */
387
+ onKeyLookup?: JWSSessionKeyLookup<T, MaxAge, TEvent>;
388
+ }
389
+ /**
390
+ * Returns the key that verifies an incoming token, picked from its protected header, by `kid` when keys rotate: an HMAC or public JWK, a
391
+ * `CryptoKey` or a JWK Set, the shapes `key` takes for verification. Set, it replaces `key` for verification: the token's `alg` is still one
392
+ * `key` serves or `verifyOptions.algorithms` lists. A `CryptoKey` it returns names no algorithm of its own: as for a lone `CryptoKey` key,
393
+ * `verifyOptions.algorithms` or the pin names what it serves. A JWK Set offers the token its keys of the token's `kid` (all of them when it
394
+ * names none) that serve its `alg`, in order, and a token offered more than `verifyOptions.limits.keyCandidates` keys is refused. Nothing
395
+ * it returns is checked when the session is defined. `undefined` means no key for this token: the token fails with
396
+ * `ERR_SESSION_TOKEN_INVALID`, an `ERR_JWK_KEY_NOT_FOUND` as its `cause`, and its cookie is expired. Any throw, a `JWTError` or not, means
397
+ * the token could not be read: `ERR_SESSION_READ_FAILED`, the thrown error as its `cause`, and the cookie is kept. A key it returns that cannot
398
+ * be used for the token's `alg` is the same read failure, an `ERR_JWK_INVALID` as its `cause`. `open()` passes it no event.
399
+ */
400
+ type JWSSessionKeyLookup<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> = (lookup: {
401
+ header: JWSHeaderParameters;
402
+ config: SessionConfigJWS<T, MaxAge, TEvent>;
403
+ event?: TEvent;
404
+ }) => JWSVerifyJWK | CryptoKey | JWKSet | undefined | Promise<JWSVerifyJWK | CryptoKey | JWKSet | undefined>;
405
+ /** Configuration of a JWS session, signed but not encrypted. */
13
406
  interface SessionConfigJWS<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> extends JWSSessionConfig<MaxAge, CookieAttributes> {
14
- /** Cookie and session-header name. Default `"unjwt-jws"`; a `.<digits>` suffix throws `ERR_SESSION_CONFIG_INVALID`. */
407
+ /** Cookie name, also the base of the default session header `x-unjwt-jws-session`. A trailing `.<digits>` throws `ERR_SESSION_CONFIG_INVALID`. @default "__Host-unjwt-jws" */
15
408
  name?: string;
409
+ /** Lifecycle hooks and `onKeyLookup`. */
16
410
  hooks?: SessionHooksJWS<T, MaxAge, TEvent>;
17
411
  }
18
- /** Defines a JWS (signed, not encrypted) session once, its data readable by clients; `use`, `token`, `issue` and `open` serve every request. */
412
+ /**
413
+ * Defines a JWS session once: signed, not encrypted, so clients can read its data. `use`, `token`, `issue` and `open` serve every request.
414
+ * @throws `ERR_SESSION_CONFIG_INVALID` if `name`, `sessionHeader`, a `__Host-` or `__Secure-` cookie's attributes or `rolling` is invalid, or a key that names no algorithm (a `CryptoKey`, an `oct` JWK without `alg`, a pair when neither half names one) lacks a pinned `jws.signOptions.alg`, or `jws.verifyOptions.algorithms` is empty or lists one no key serves without `onKeyLookup`, or names none of those a `publicKey` entry without `alg` carries, or a token of a JWK Set `key` entry without `kid` meets more than `jws.verifyOptions.limits.keyCandidates` entries.
415
+ * @throws `ERR_SESSION_KEY_INVALID` if `key` is missing, a string, a lone asymmetric key, not an HMAC `oct` JWK, a JWK Set of them, a secret `CryptoKey` or a key pair, an empty JWK Set or one holding a key that is not an `oct` JWK, a pair with a half that is not what it is named, serves no JWS algorithm, or cannot serve the pinned `alg` or, for a pair's half that names none, the one its other half names, or a pair whose single `publicKey` names another algorithm than the one it issues under, or whose `publicKey` list or JWK Set holds no key that serves it.
416
+ * @throws `ERR_INVALID_OPTION` if `rolling` is neither `true` nor a duration.
417
+ */
19
418
  export declare function defineJWSSession<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends WebSessionEvent = WebSessionEvent>(config: SessionConfigJWS<T, MaxAge, TEvent>): SessionDefinition<T, MaxAge, TEvent>;
20
- /** Defines a JWS (signed, not encrypted) session over a framework driver of your own. */
419
+ /**
420
+ * Defines a JWS session over a framework driver of your own, passed as `{ driver }`.
421
+ * @throws `ERR_SESSION_CONFIG_INVALID` if `name`, `sessionHeader`, a `__Host-` or `__Secure-` cookie's attributes or `rolling` is invalid, or a key that names no algorithm (a `CryptoKey`, an `oct` JWK without `alg`, a pair when neither half names one) lacks a pinned `jws.signOptions.alg`, or `jws.verifyOptions.algorithms` is empty or lists one no key serves without `onKeyLookup`, or names none of those a `publicKey` entry without `alg` carries, or a token of a JWK Set `key` entry without `kid` meets more than `jws.verifyOptions.limits.keyCandidates` entries.
422
+ * @throws `ERR_SESSION_KEY_INVALID` if `key` is missing, a string, a lone asymmetric key, not an HMAC `oct` JWK, a JWK Set of them, a secret `CryptoKey` or a key pair, an empty JWK Set or one holding a key that is not an `oct` JWK, a pair with a half that is not what it is named, serves no JWS algorithm, or cannot serve the pinned `alg` or, for a pair's half that names none, the one its other half names, or a pair whose single `publicKey` names another algorithm than the one it issues under, or whose `publicKey` list or JWK Set holds no key that serves it.
423
+ * @throws `ERR_INVALID_OPTION` if `rolling` is neither `true` nor a duration.
424
+ */
21
425
  export declare function defineJWSSession<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent>(config: SessionConfigJWS<T, MaxAge, TEvent>, options: {
22
426
  driver: SessionDriver<TEvent>;
23
427
  }): SessionDefinition<T, MaxAge, TEvent>;
24
- /** Session state for the current request, mirroring the claims of its JWE token. */
428
+ /** An `oct` JWK that JWE key management accepts. */
429
+ type JWESessionOctJWK = Extract<JWEDecryptJWK, {
430
+ kty: "oct";
431
+ }>;
432
+ /**
433
+ * A symmetric key that encrypts and decrypts, an `oct` JWK or a secret `CryptoKey`, or a JWK Set of `oct` JWKs. A key without `alg` (a
434
+ * `CryptoKey`, an `oct` JWK without `alg`) requires a pinned `jwe.encryptOptions.alg` and `enc`. A JWK Set's first key encrypts and
435
+ * every key decrypts, each checked as a lone key, the pin naming the first alone; a token of a key without `kid` may meet at most
436
+ * `jwe.decryptOptions.limits.keyCandidates` keys, those whose `alg` serves it and those without `alg`. An asymmetric key throws `ERR_SESSION_KEY_INVALID`: its public half encrypts, so anyone holding that half
437
+ * could forge a session the server accepts. Use `defineJWSSession` for a key pair.
438
+ */
439
+ type JWESessionKey = JWESessionOctJWK | CryptoKey | JWKSet<JWESessionOctJWK[]>;
440
+ /**
441
+ * JWE decrypt options a session accepts. `algorithms` names the `alg` values a key without its own `alg` (a `CryptoKey`, an `oct` JWK
442
+ * without `alg`) decrypts, and with `onKeyLookup` set, may also name those only the keys it returns serve. The session sets `typ`,
443
+ * `maxTokenAge`, `validateClaims` and `payload` itself, and takes no `encryptionAlgorithms`: a key decrypts every `enc` it serves.
444
+ */
445
+ type SessionDecryptOptions = StrictOmit<JWEDecryptOptions, "encryptionAlgorithms" | "typ" | "maxTokenAge" | "validateClaims" | "payload">;
446
+ /** JWE encrypt options a session accepts. The session sets `exp` from `maxAge` and never sets `nbf`. */
447
+ type SessionEncryptOptions = StrictOmit<JWEEncryptOptions, "expiresIn" | "expiresAt" | "notBeforeIn" | "notBeforeAt">;
448
+ /** The JWE options of a session: `encryptOptions` for each issued token, `decryptOptions` for each incoming one. */
449
+ interface JWESessionOptions {
450
+ encryptOptions?: SessionEncryptOptions;
451
+ decryptOptions?: SessionDecryptOptions;
452
+ }
453
+ /** The config of a JWE session, without its hooks. */
454
+ interface JWESessionConfig<MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TCookie extends object = object> extends SessionBaseConfig<MaxAge> {
455
+ /** The key, or JWK Set, that encrypts and decrypts the token. See {@link JWESessionKey}. */
456
+ key: JWESessionKey;
457
+ /** Cookie attributes, or `false` for no cookie. `chunkMaxLength` is the size the token is split at (`4000` when unset). @default { path: "/", secure: true, httpOnly: true, sameSite: "lax" } */
458
+ cookie?: false | (TCookie & {
459
+ chunkMaxLength?: number;
460
+ });
461
+ /**
462
+ * `encryptOptions.alg` and `enc` are what each token is encrypted with, and name the algorithm of a key without its own `alg`.
463
+ * Decryption accepts every `alg` the key serves: a JWK's own `alg`, and for a key without one, the pin and each algorithm of
464
+ * `decryptOptions.algorithms` its material carries. An empty `decryptOptions.algorithms`, or one listing an algorithm no key serves,
465
+ * throws `ERR_SESSION_CONFIG_INVALID`, unless `onKeyLookup` is set for the latter. A `dir` key decrypts its own `enc` alone, a wrapping
466
+ * key every `enc`. `encryptOptions.protectedHeader.typ` defaults to `"session+jwt"` (RFC 8725 §3.11). A PBES2 session accepts at most
467
+ * the `p2c` it issues with, unless `decryptOptions.maxIterations` is set.
468
+ */
469
+ jwe?: JWESessionOptions;
470
+ }
471
+ /** Session state for the current request, from the claims of its JWE token. */
25
472
  interface SessionJWE<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> extends SessionState<T, MaxAge> {}
26
- /** JWE session hooks; `onRead`, `onExpire` and `onError` are mutually exclusive per token. */
27
- interface SessionHooksJWE<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> extends JWESessionHooks<SessionJWE<T, MaxAge>, SessionManager<T, MaxAge>, {
473
+ /** JWE session hooks. `onRead`, `onExpire` and `onError` are mutually exclusive per token. */
474
+ interface SessionHooksJWE<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> extends SessionHooks<SessionJWE<T, MaxAge>, SessionManager<T, MaxAge>, {
28
475
  event: TEvent;
29
- }, SessionConfigJWE<T, MaxAge, TEvent>> {}
30
- /** Configuration for a JWE-backed (encrypted) session. */
476
+ }, SessionConfigJWE<T, MaxAge, TEvent>> {
477
+ /** Returns the key that decrypts an incoming token. See {@link JWESessionKeyLookup}. */
478
+ onKeyLookup?: JWESessionKeyLookup<T, MaxAge, TEvent>;
479
+ }
480
+ /**
481
+ * Returns the key that decrypts an incoming token, picked from its protected header, by `kid` when keys rotate: an `oct` JWK, a
482
+ * `CryptoKey` or a JWK Set, the shapes `key` takes for decryption. Set, it replaces `key` for decryption: the token's `alg` is still one
483
+ * `key` serves or `decryptOptions.algorithms` lists. A `CryptoKey` it returns names no algorithm of its own: as for a lone `CryptoKey` key,
484
+ * `decryptOptions.algorithms` or the pin names what it serves. A JWK Set offers the token its keys of the token's `kid` (all of them when it
485
+ * names none) that serve its `alg`, in order, and a token offered more than `decryptOptions.limits.keyCandidates` keys is refused. Nothing
486
+ * it returns is checked when the session is defined. `undefined` means no key for this token: the token fails with
487
+ * `ERR_SESSION_TOKEN_INVALID`, an `ERR_JWK_KEY_NOT_FOUND` as its `cause`, and its cookie is expired. Any throw, a `JWTError` or not, means
488
+ * the token could not be read: `ERR_SESSION_READ_FAILED`, the thrown error as its `cause`, and the cookie is kept. A key it returns that cannot
489
+ * be used for the token's `alg` is the same read failure, an `ERR_JWK_INVALID` as its `cause`. `open()` passes it no event.
490
+ */
491
+ type JWESessionKeyLookup<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> = (lookup: {
492
+ header: JWEHeaderParameters;
493
+ config: SessionConfigJWE<T, MaxAge, TEvent>;
494
+ event?: TEvent;
495
+ }) => JWEDecryptJWK | CryptoKey | JWKSet | undefined | Promise<JWEDecryptJWK | CryptoKey | JWKSet | undefined>;
496
+ /** Configuration of an encrypted JWE session. */
31
497
  interface SessionConfigJWE<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent> extends JWESessionConfig<MaxAge, CookieAttributes> {
32
- /** Cookie and session-header name. Default `"unjwt-jwe"`; a `.<digits>` suffix throws `ERR_SESSION_CONFIG_INVALID`. */
498
+ /** Cookie name, also the base of the default session header `x-unjwt-jwe-session`. A trailing `.<digits>` throws `ERR_SESSION_CONFIG_INVALID`. @default "__Host-unjwt-jwe" */
33
499
  name?: string;
500
+ /** Lifecycle hooks and `onKeyLookup`. */
34
501
  hooks?: SessionHooksJWE<T, MaxAge, TEvent>;
35
502
  }
36
- /** Defines a JWE (encrypted) session once; `use`, `token`, `issue` and `open` serve every request. */
503
+ /**
504
+ * Defines a JWE session once: encrypted, so clients cannot read its data. `use`, `token`, `issue` and `open` serve every request.
505
+ * @throws `ERR_SESSION_CONFIG_INVALID` if `name`, `sessionHeader`, a `__Host-` or `__Secure-` cookie's attributes or `rolling` is invalid, or a key that names no algorithm (a `CryptoKey`, an `oct` JWK without `alg`) lacks a pinned `jwe.encryptOptions.alg` and `enc`, or `jwe.decryptOptions.algorithms` is empty or lists one no key serves without `onKeyLookup`, or a token of a JWK Set `key` entry without `kid` meets more than `jwe.decryptOptions.limits.keyCandidates` entries.
506
+ * @throws `ERR_SESSION_KEY_INVALID` if `key` is missing, a string, asymmetric, not an `oct` JWK, a JWK Set of them or a secret `CryptoKey`, an empty JWK Set or one holding a key that is not an `oct` JWK, serves no JWE algorithm, or cannot serve the pinned `alg` or `enc`.
507
+ * @throws `ERR_INVALID_OPTION` if `rolling` is neither `true` nor a duration.
508
+ */
37
509
  export declare function defineJWESession<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends WebSessionEvent = WebSessionEvent>(config: SessionConfigJWE<T, MaxAge, TEvent>): SessionDefinition<T, MaxAge, TEvent>;
38
- /** Defines a JWE (encrypted) session over a framework driver of your own. */
510
+ /**
511
+ * Defines a JWE session over a framework driver of your own, passed as `{ driver }`.
512
+ * @throws `ERR_SESSION_CONFIG_INVALID` if `name`, `sessionHeader`, a `__Host-` or `__Secure-` cookie's attributes or `rolling` is invalid, or a key that names no algorithm (a `CryptoKey`, an `oct` JWK without `alg`) lacks a pinned `jwe.encryptOptions.alg` and `enc`, or `jwe.decryptOptions.algorithms` is empty or lists one no key serves without `onKeyLookup`, or a token of a JWK Set `key` entry without `kid` meets more than `jwe.decryptOptions.limits.keyCandidates` entries.
513
+ * @throws `ERR_SESSION_KEY_INVALID` if `key` is missing, a string, asymmetric, not an `oct` JWK, a JWK Set of them or a secret `CryptoKey`, an empty JWK Set or one holding a key that is not an `oct` JWK, serves no JWE algorithm, or cannot serve the pinned `alg` or `enc`.
514
+ * @throws `ERR_INVALID_OPTION` if `rolling` is neither `true` nor a duration.
515
+ */
39
516
  export declare function defineJWESession<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent>(config: SessionConfigJWE<T, MaxAge, TEvent>, options: {
40
517
  driver: SessionDriver<TEvent>;
41
518
  }): SessionDefinition<T, MaxAge, TEvent>;
42
- /** Types a session driver for a framework; pass it to `defineJWSSession` / `defineJWESession` as `{ driver }`. */
519
+ /**
520
+ * Returns `driver` typed as a `SessionDriver`. Pass it to `defineJWSSession` or `defineJWESession` as `{ driver }`.
521
+ * The Web driver, `webSessionDriver()`, is the reference implementation of the contract.
522
+ */
43
523
  export declare function defineSessionDriver<TEvent>(driver: SessionDriver<TEvent>): SessionDriver<TEvent>;
44
- export { type CompositeKey, type ContentEncryptionAlgorithm, type CookieAttributes, type CookieJar, type DeriveJWKOptions, type DeriveJWKReturn, type DeriveKeyOptions, type DeriveKeyReturn, type Duration, type ECDHEphemeralKeyInput, type ExpiresIn, type GenerateJWKOptions, type GenerateJWKReturn, type GenerateKeyAlgorithm, type GenerateKeyOptions, type GenerateKeyReturn, type GeneratedJWKMap, type GeneratedKeyMap, type ImportedKey, type ImportedKeyMap, type ImportedPEMJWK, type JOSEConsumerOptions, type JOSELimits, type JOSEPayload, type JOSEPayloadMode, type JOSEPayloadTypeMap, type JWEAsymmetricPrivateJWK, type JWEAsymmetricPublicJWK, type JWEDecryptJWK, type JWEDecryptOptions, type JWEDecryptResult, type JWEEncryptJWK, type JWEEncryptOptions, type JWEFlattenedSerialization, type JWEGeneralRecipient, type JWEGeneralSerialization, type JWEHeaderParameters, type JWEKeyLookup, type JWEKeyManagementHeaderParameters, type JWELibraryHeaderName, type JWEMultiDecryptKey, type JWEMultiDecryptOptions, type JWEMultiDecryptResult, type JWEMultiEncryptOptions, type JWEMultiRecipient, type JWEProtectedHeader, type JWK, type JWKAlgorithm, type JWKCacheAdapter, type JWKLookupFunction, type JWKLookupFunctionHeader, type JWKMetadata, type JWKPEMAlgorithm, type JWKParameters, type JWKSet, type JWK_AES_Algorithm, type JWK_AES_CBC_HMAC, type JWK_AES_GCM, type JWK_AES_GCM_KW, type JWK_AES_KW, type JWK_Asymmetric, type JWK_Asymmetric_Algorithm, type JWK_EC, type JWK_ECDH_ES, type JWK_ECDSA, type JWK_EC_Private, type JWK_EC_Public, type JWK_HMAC, type JWK_OKP, type JWK_OKP_Private, type JWK_OKP_Public, type JWK_OKP_SIGN, type JWK_PBES2, type JWK_Pair, type JWK_Private, type JWK_Public, type JWK_RSA, type JWK_RSA_ENC, type JWK_RSA_PSS, type JWK_RSA_Private, type JWK_RSA_Public, type JWK_RSA_SIGN, type JWK_Symmetric, type JWK_Symmetric_Algorithm, type JWK_oct, type JWSAlgorithm, type JWSAsymmetricPrivateJWK, type JWSAsymmetricPublicJWK, type JWSFlattenedSerialization, type JWSGeneralSerialization, type JWSGeneralSignature, type JWSHashedAlgorithm, type JWSHeaderParameters, type JWSKeyLookup, type JWSMultiSignOptions, type JWSMultiSigner, type JWSMultiVerifyAllOptions, type JWSMultiVerifyOptions, type JWSMultiVerifyOutcome, type JWSMultiVerifyResult, type JWSProtectedHeader, type JWSSignJWK, type JWSSignOptions, type JWSVerifyJWK, type JWSVerifyOptions, type JWSVerifyResult, type JWT, type JWTClaimValidationOptions, type JWTClaims, type JWTConfirmation, type JWTTimeClaimOptions, type JoseHeaderParameters, type KeyManagementAlgorithm, type KeyWrapAlgorithmOf, type KeyWrappingAlgorithm, type MaxTokenAge, type NotBeforeIn, type OpenedSessionState, type PEMType, type PayloadOf, type SessionClaims, type SessionConfigJWE, type SessionConfigJWS, type SessionData, type SessionDecryptOptions, type SessionDefinition, type SessionDriver, type SessionEncryptOptions, type SessionHandedToken, type SessionHooksJWE, type SessionHooksJWS, type SessionIssueOptions, type SessionJWE, type SessionJWS, type SessionManager, type SessionRequestEvent, type SessionSignOptions, type SessionUpdate, type SessionUpdateTrigger, type SessionVerifyOptions, type ToPublicJWKReturn, type UnwrapKeyOptions, type UnwrapKeyResult, type UnwrappingKeyFor, type WebSessionEvent, type WrapKeyOptions, type WrapKeyResult, type WrappingKeyFor, deriveJWKFromPassword, exportPEM, generateJWK, importPEM, thumbprint, toPublicJWK };
524
+ /**
525
+ * The Web session driver: a request event by its `Request` or its `Headers`, or a token in hand.
526
+ * `prefix` (default `"[unjwt/session]"`) starts the message of every error a session over it throws, the driver's own included.
527
+ * Every driver it returns shares the state of a request with the others.
528
+ */
529
+ export declare function webSessionDriver(options?: {
530
+ prefix?: string;
531
+ }): SessionDriver<WebSessionEvent>;
532
+ /**
533
+ * A cookie jar over a request's `Headers` and, when given, its response's: `read` parses the request's `Cookie` header,
534
+ * `write` sets a `Set-Cookie` line on `response.headers` through `serializeCookie`, replacing the line of the same cookie
535
+ * (name, domain, path, partition) instead of adding a second one, and `written` reads back what the response sets.
536
+ * Each write is copied to `errHeaders` too: h3 and Nitro send only these for a thrown handler.
537
+ * Without `response`, the jar only reads.
538
+ */
539
+ export declare function webCookieJar(request: Headers, response?: {
540
+ headers: Headers;
541
+ errHeaders?: Headers;
542
+ }): CookieJar<CookieAttributes>;
543
+ /** The cookies of a `Cookie` header value, by name, values percent-decoded. The first of two cookies with one name wins. The record has no prototype. */
544
+ export declare function parseCookie(header: string): Record<string, string | undefined>;
545
+ /** One `Set-Cookie` line, the value percent-encoded and `path` `"/"` unless `attrs` sets one. Throws a `TypeError` for a name or attribute RFC 6265bis refuses. */
546
+ export declare function serializeCookie(name: string, value: string, attrs?: CookieAttributes): string;
547
+ /** The members of a session config that {@link assertSessionConfig} checks. */
548
+ interface SessionConfigChecks {
549
+ /** Request header to read the token from: a name, or `true` for `x-<name>-session`. */
550
+ sessionHeader?: boolean | string;
551
+ /** Cookie attributes over the defaults, or `false` for no cookie. */
552
+ cookie?: false | (CookieAttributes & {
553
+ chunkMaxLength?: number;
554
+ });
555
+ /** Session lifetime. */
556
+ maxAge?: ExpiresIn;
557
+ /** Reissues a session read from its cookie: on every read with `true`, else once the token is that old. Requires `maxAge`, and is shorter than it. */
558
+ rolling?: true | ExpiresIn;
559
+ }
560
+ /**
561
+ * Checks what the config alone decides: its name, session header, cookie prefix over `defaultCookie`, and `rolling`.
562
+ * `defaultCookie` is {@link DEFAULT_SESSION_COOKIE} when unset.
563
+ * @throws `ERR_SESSION_CONFIG_INVALID` if `name` is not a cookie name or ends in a dot and digits, `sessionHeader` is not a header name,
564
+ * a `__Host-` or `__Secure-` cookie's attributes break its prefix rules, or `rolling` has no `maxAge` or is not shorter than it. The message starts with `prefix`.
565
+ * @throws `ERR_INVALID_OPTION` if `rolling` is neither `true` nor a duration.
566
+ */
567
+ export declare function assertSessionConfig(config: SessionConfigChecks, options: {
568
+ name: string;
569
+ prefix: string;
570
+ defaultCookie?: CookieAttributes;
571
+ }): void;
572
+ /**
573
+ * The transport options of a session config: its session header, and its cookie attributes over `defaultCookie` with `chunkMaxLength` set apart.
574
+ * `defaultCookie` is {@link DEFAULT_SESSION_COOKIE} when unset. `cookie: false` is no cookie.
575
+ */
576
+ export declare function sessionTransportOptions(config: Pick<SessionConfigChecks, "sessionHeader" | "cookie">, options: {
577
+ name: string;
578
+ defaultCookie?: CookieAttributes;
579
+ }): SessionTransportOptions;
580
+ /**
581
+ * Claims a session name on one request: one name is one cookie, so the first family to claim a name on a request keeps it.
582
+ * `state` is `driver.state(event)`. The same family may claim a name again on the same request.
583
+ * @throws `ERR_SESSION_CONFIG_INVALID` if another family already claimed `name` on this request. The message starts with `prefix`.
584
+ */
585
+ export declare function claimSessionName(state: Record<string, unknown>, options: {
586
+ name: string;
587
+ family: string;
588
+ prefix: string;
589
+ }): void;
590
+ export { type CompositeKey, type ContentEncryptionAlgorithm, type CookieAttributes, type CookieJar, type DeriveJWKOptions, type DeriveJWKReturn, type DeriveKeyOptions, type DeriveKeyReturn, type Duration, type ECDHEphemeralKeyInput, type ExpiresIn, type GenerateJWKOptions, type GenerateJWKReturn, type GenerateKeyAlgorithm, type GenerateKeyOptions, type GenerateKeyReturn, type GeneratedJWKMap, type GeneratedKeyMap, type ImportedKey, type ImportedKeyMap, type ImportedPEMJWK, type JOSEConsumerOptions, type JOSELimits, type JOSEPayload, type JOSEPayloadMode, type JOSEPayloadTypeMap, type JWEAsymmetricPrivateJWK, type JWEAsymmetricPublicJWK, type JWEDecryptJWK, type JWEDecryptOptions, type JWEDecryptResult, type JWEEncryptJWK, type JWEEncryptOptions, type JWEFlattenedSerialization, type JWEGeneralRecipient, type JWEGeneralSerialization, type JWEHeaderParameters, type JWEKeyLookup, type JWEKeyManagementHeaderParameters, type JWELibraryHeaderName, type JWEMultiDecryptKey, type JWEMultiDecryptOptions, type JWEMultiDecryptResult, type JWEMultiEncryptOptions, type JWEMultiRecipient, type JWEProtectedHeader, type JWESessionKey, type JWESessionKeyLookup, type JWESessionOctJWK, type JWK, type JWKAlgorithm, type JWKCacheAdapter, type JWKLookupFunction, type JWKLookupFunctionHeader, type JWKMetadata, type JWKPEMAlgorithm, type JWKParameters, type JWKSet, type JWK_AES_Algorithm, type JWK_AES_CBC_HMAC, type JWK_AES_GCM, type JWK_AES_GCM_KW, type JWK_AES_KW, type JWK_Asymmetric, type JWK_Asymmetric_Algorithm, type JWK_EC, type JWK_ECDH_ES, type JWK_ECDSA, type JWK_EC_Private, type JWK_EC_Public, type JWK_HMAC, type JWK_OKP, type JWK_OKP_Private, type JWK_OKP_Public, type JWK_OKP_SIGN, type JWK_PBES2, type JWK_Pair, type JWK_Private, type JWK_Public, type JWK_RSA, type JWK_RSA_ENC, type JWK_RSA_PSS, type JWK_RSA_Private, type JWK_RSA_Public, type JWK_RSA_SIGN, type JWK_Symmetric, type JWK_Symmetric_Algorithm, type JWK_oct, type JWSAlgorithm, type JWSAsymmetricPrivateJWK, type JWSAsymmetricPublicJWK, type JWSFlattenedSerialization, type JWSGeneralSerialization, type JWSGeneralSignature, type JWSHashedAlgorithm, type JWSHeaderParameters, type JWSKeyLookup, type JWSMultiSignOptions, type JWSMultiSigner, type JWSMultiVerifyAllOptions, type JWSMultiVerifyOptions, type JWSMultiVerifyOutcome, type JWSMultiVerifyResult, type JWSProtectedHeader, type JWSSessionKey, type JWSSessionKeyLookup, type JWSSignJWK, type JWSSignOptions, type JWSVerifyJWK, type JWSVerifyOptions, type JWSVerifyResult, type JWT, type JWTClaimValidationOptions, type JWTClaims, type JWTConfirmation, type JWTTimeClaimOptions, type JoseHeaderParameters, type KeyManagementAlgorithm, type KeyWrapAlgorithmOf, type KeyWrappingAlgorithm, type MaxTokenAge, type NotBeforeIn, type OpenedSessionState, type PEMType, type PayloadOf, type SessionClaims, type SessionConfigChecks, type SessionConfigJWE, type SessionConfigJWS, type SessionData, type SessionDecryptOptions, type SessionDefinition, type SessionDriver, type SessionEncryptOptions, type SessionHandedToken, type SessionHooksJWE, type SessionHooksJWS, type SessionIssueOptions, type SessionJWE, type SessionJWS, type SessionManager, type SessionRequestEvent, type SessionSignOptions, type SessionSource, type SessionTransport, type SessionTransportOptions, type SessionUpdate, type SessionUpdateTrigger, type SessionVerifyOptions, type ToPublicJWKReturn, type UnwrapKeyOptions, type UnwrapKeyResult, type UnwrappingKeyFor, type WebSessionEvent, type WrapKeyOptions, type WrapKeyResult, type WrappingKeyFor, deriveJWKFromPassword, exportPEM, generateJWK, importPEM, thumbprint, toPublicJWK };