unjwt 0.5.39 → 0.6.0
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 +156 -13
- package/dist/_chunks/_crypto.mjs +1014 -0
- package/dist/_chunks/error.d.mts +67 -0
- package/dist/_chunks/index.d.mts +631 -219
- package/dist/_chunks/jwk.d.mts +220 -87
- package/dist/_chunks/jws.mjs +729 -682
- package/dist/_chunks/utils.mjs +74 -69
- package/dist/adapters/h3v1/index.d.mts +282 -0
- package/dist/{_chunks/h3v1.mjs → adapters/h3v1/index.mjs} +204 -91
- package/dist/adapters/h3v2/index.d.mts +213 -0
- package/dist/adapters/{h3v2.mjs → h3v2/index.mjs} +215 -113
- package/dist/core/_crypto/index.d.mts +71 -0
- package/dist/core/_crypto/index.mjs +2 -0
- package/dist/core/jwe.d.mts +40 -0
- package/dist/{_chunks → core}/jwe.mjs +61 -32
- package/dist/core/jwk.d.mts +231 -0
- package/dist/core/jwk.mjs +686 -0
- package/dist/core/jws.d.mts +31 -0
- package/dist/core/jws.mjs +104 -0
- package/dist/{_chunks/index2.d.mts → core/utils/index.d.mts} +13 -12
- package/dist/core/utils/index.mjs +2 -0
- package/dist/index.d.mts +7 -6
- package/dist/index.mjs +5 -5
- package/package.json +50 -41
- package/dist/_chunks/chunk.mjs +0 -13
- package/dist/_chunks/jwe.d.mts +0 -43
- package/dist/_chunks/jwk.mjs +0 -1592
- package/dist/_chunks/jws.d.mts +0 -46
- package/dist/adapters/h3.d.mts +0 -3
- package/dist/adapters/h3.mjs +0 -3
- package/dist/adapters/h3v1.d.mts +0 -3
- package/dist/adapters/h3v1.mjs +0 -3
- package/dist/adapters/h3v2.d.mts +0 -184
- package/dist/jwe.d.mts +0 -3
- package/dist/jwe.mjs +0 -4
- package/dist/jwk.d.mts +0 -3
- package/dist/jwk.mjs +0 -3
- package/dist/jws.d.mts +0 -3
- package/dist/jws.mjs +0 -4
- package/dist/utils.d.mts +0 -3
- package/dist/utils.mjs +0 -2
package/dist/_chunks/utils.mjs
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/core/error.ts
|
|
2
|
+
/**
|
|
3
|
+
* Base error class for all unjwt errors. Every error thrown by the library is
|
|
4
|
+
* an instance of `JWTError`, so a single `instanceof` check is sufficient to
|
|
5
|
+
* distinguish library errors from other thrown values. Use the `code` property
|
|
6
|
+
* (or the `isJWTError` type guard) to narrow to a specific error condition.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import { JWTError, isJWTError } from "unjwt/jws";
|
|
10
|
+
*
|
|
11
|
+
* try {
|
|
12
|
+
* await verify(token, key);
|
|
13
|
+
* } catch (err) {
|
|
14
|
+
* if (isJWTError(err, "ERR_JWT_EXPIRED")) {
|
|
15
|
+
* console.log(err.cause.jti); // string | undefined
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
var JWTError = class extends Error {
|
|
20
|
+
code;
|
|
21
|
+
cause;
|
|
22
|
+
constructor(message, code, cause) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "JWTError";
|
|
25
|
+
this.code = code;
|
|
26
|
+
this.cause = cause;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
function isJWTError(error, code) {
|
|
30
|
+
if (!(error instanceof JWTError)) return false;
|
|
31
|
+
return code === void 0 || error.code === code;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
2
34
|
//#region src/core/utils/jwt.ts
|
|
3
35
|
/**
|
|
4
36
|
* Apply default typ/cty semantics shared by JWS & JWE.
|
|
@@ -107,23 +139,31 @@ function validateJwtClaims(jwtClaims, options = {}) {
|
|
|
107
139
|
if (options.subject) allRequiredClaims.add("sub");
|
|
108
140
|
if (options.maxTokenAge) allRequiredClaims.add("iat");
|
|
109
141
|
for (const claimName of allRequiredClaims) if (!(claimName in jwtClaims)) missingClaims.add(claimName);
|
|
110
|
-
if (missingClaims.size > 0) throw new
|
|
142
|
+
if (missingClaims.size > 0) throw new JWTError(`Missing required JWT Claims: ${[...missingClaims].join(", ")}`, "ERR_JWT_CLAIM_MISSING");
|
|
111
143
|
if (options.issuer) {
|
|
112
144
|
const expectedIssuers = maybeArray(options.issuer);
|
|
113
|
-
if (!jwtClaims.iss || !expectedIssuers.includes(jwtClaims.iss)) throw new
|
|
145
|
+
if (!jwtClaims.iss || !expectedIssuers.includes(jwtClaims.iss)) throw new JWTError(`Invalid JWT "iss" (Issuer) Claim: Expected ${expectedIssuers.join(" or ")}, got ${jwtClaims.iss}`, "ERR_JWT_CLAIM_INVALID");
|
|
114
146
|
}
|
|
115
|
-
if (options.subject && jwtClaims.sub !== options.subject) throw new
|
|
147
|
+
if (options.subject && jwtClaims.sub !== options.subject) throw new JWTError(`Invalid JWT "sub" (Subject) Claim: Expected ${options.subject}, got ${jwtClaims.sub}`, "ERR_JWT_CLAIM_INVALID");
|
|
116
148
|
if (options.audience) {
|
|
117
149
|
const expectedAudiences = maybeArray(options.audience);
|
|
118
150
|
const claimAudience = maybeArray(jwtClaims.aud || []);
|
|
119
|
-
if (!claimAudience.some((aud) => expectedAudiences.includes(aud))) throw new
|
|
151
|
+
if (!claimAudience.some((aud) => expectedAudiences.includes(aud))) throw new JWTError(`Invalid JWT "aud" (Audience) Claim: Expected ${expectedAudiences.join(" or ")}, got ${claimAudience.join(", ")}`, "ERR_JWT_CLAIM_INVALID");
|
|
120
152
|
}
|
|
121
|
-
if (typeof jwtClaims.nbf === "number" && jwtClaims.nbf > currentTime + clockTolerance) throw new
|
|
122
|
-
if (typeof jwtClaims.exp === "number" && jwtClaims.exp <= currentTime - clockTolerance) throw new
|
|
153
|
+
if (typeof jwtClaims.nbf === "number" && jwtClaims.nbf > currentTime + clockTolerance) throw new JWTError(`JWT "nbf" (Not Before) Claim validation failed: Token is not yet valid (nbf: ${(/* @__PURE__ */ new Date(jwtClaims.nbf * 1e3)).toISOString()})`, "ERR_JWT_NBF");
|
|
154
|
+
if (typeof jwtClaims.exp === "number" && jwtClaims.exp <= currentTime - clockTolerance) throw new JWTError(`JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${(/* @__PURE__ */ new Date(jwtClaims.exp * 1e3)).toISOString()})`, "ERR_JWT_EXPIRED", {
|
|
155
|
+
jti: jwtClaims.jti,
|
|
156
|
+
iat: jwtClaims.iat,
|
|
157
|
+
exp: jwtClaims.exp
|
|
158
|
+
});
|
|
123
159
|
if (options.maxTokenAge) {
|
|
124
|
-
if (typeof jwtClaims.iat !== "number") throw new
|
|
125
|
-
if (jwtClaims.iat > currentTime + clockTolerance) throw new
|
|
126
|
-
if (jwtClaims.iat < currentTime - computeMaxTokenAgeSeconds(options.maxTokenAge) - clockTolerance) throw new
|
|
160
|
+
if (typeof jwtClaims.iat !== "number") throw new JWTError("JWT \"iat\" (Issued At) Claim must be a number when maxTokenAge is set.", "ERR_JWT_CLAIM_INVALID");
|
|
161
|
+
if (jwtClaims.iat > currentTime + clockTolerance) throw new JWTError(`JWT "iat" (Issued At) Claim validation failed: Token was issued in the future (iat: ${(/* @__PURE__ */ new Date(jwtClaims.iat * 1e3)).toISOString()})`, "ERR_JWT_CLAIM_INVALID");
|
|
162
|
+
if (jwtClaims.iat < currentTime - computeMaxTokenAgeSeconds(options.maxTokenAge) - clockTolerance) throw new JWTError(`JWT "iat" (Issued At) Claim validation failed: Token is too old (maxTokenAge: ${options.maxTokenAge}s, iat: ${(/* @__PURE__ */ new Date(jwtClaims.iat * 1e3)).toISOString()})`, "ERR_JWT_EXPIRED", {
|
|
163
|
+
jti: jwtClaims.jti,
|
|
164
|
+
iat: jwtClaims.iat,
|
|
165
|
+
exp: jwtClaims.exp
|
|
166
|
+
});
|
|
127
167
|
}
|
|
128
168
|
}
|
|
129
169
|
const BASE_HEADER_PARAMS = [
|
|
@@ -138,11 +178,11 @@ const BASE_HEADER_PARAMS = [
|
|
|
138
178
|
"x5u"
|
|
139
179
|
];
|
|
140
180
|
/** Validate critical headers in JWS semantics. */
|
|
141
|
-
function validateCriticalHeadersJWS(protectedHeader,
|
|
181
|
+
function validateCriticalHeadersJWS(protectedHeader, recognizedHeaders = []) {
|
|
142
182
|
if (!protectedHeader.crit) return;
|
|
143
183
|
const missingHeaderParams = /* @__PURE__ */ new Set();
|
|
144
184
|
const recognizedParams = new Set([
|
|
145
|
-
...
|
|
185
|
+
...recognizedHeaders,
|
|
146
186
|
...BASE_HEADER_PARAMS,
|
|
147
187
|
"b64"
|
|
148
188
|
]);
|
|
@@ -150,14 +190,14 @@ function validateCriticalHeadersJWS(protectedHeader, requiredHeaders = []) {
|
|
|
150
190
|
if (recognizedParams.has(param) && (param in protectedHeader || param === "b64")) continue;
|
|
151
191
|
missingHeaderParams.add(param);
|
|
152
192
|
}
|
|
153
|
-
if (missingHeaderParams.size > 0) throw new
|
|
193
|
+
if (missingHeaderParams.size > 0) throw new JWTError(`Missing critical header parameters: ${[...missingHeaderParams].join(", ")}`, "ERR_JWS_INVALID");
|
|
154
194
|
}
|
|
155
195
|
/** Validate critical headers in JWE semantics. */
|
|
156
|
-
function validateCriticalHeadersJWE(protectedHeader,
|
|
157
|
-
if (protectedHeader.crit && !
|
|
196
|
+
function validateCriticalHeadersJWE(protectedHeader, recognizedHeaders) {
|
|
197
|
+
if (protectedHeader.crit && !recognizedHeaders) throw new JWTError(`Unprocessed critical header parameters: ${protectedHeader.crit.join(", ")}`, "ERR_JWE_INVALID");
|
|
158
198
|
if (!protectedHeader.crit) return;
|
|
159
199
|
const understoodParams = new Set([
|
|
160
|
-
...
|
|
200
|
+
...recognizedHeaders || [],
|
|
161
201
|
...BASE_HEADER_PARAMS,
|
|
162
202
|
"enc",
|
|
163
203
|
"iv",
|
|
@@ -169,76 +209,41 @@ function validateCriticalHeadersJWE(protectedHeader, understoodFromOptions) {
|
|
|
169
209
|
"apv"
|
|
170
210
|
]);
|
|
171
211
|
for (const critParam of protectedHeader.crit) {
|
|
172
|
-
if (!Object.prototype.hasOwnProperty.call(protectedHeader, critParam)) throw new
|
|
173
|
-
if (!understoodParams.has(critParam)) throw new
|
|
212
|
+
if (!Object.prototype.hasOwnProperty.call(protectedHeader, critParam)) throw new JWTError(`Critical header parameter "${critParam}" listed in "crit" but not present in the protected header.`, "ERR_JWE_INVALID");
|
|
213
|
+
if (!understoodParams.has(critParam)) throw new JWTError(`Unprocessed critical header parameters: ${critParam}`, "ERR_JWE_INVALID");
|
|
174
214
|
}
|
|
175
215
|
}
|
|
176
216
|
//#endregion
|
|
177
217
|
//#region src/core/utils/sanitize.ts
|
|
178
218
|
/**
|
|
179
|
-
*
|
|
219
|
+
* Originally derived from unsecure@0.0.4
|
|
180
220
|
* Licensed under the MIT License.
|
|
181
221
|
*
|
|
182
222
|
* Source: https://github.com/sandros94/unsecure/blob/913ed5580c551153a19154b4916c67a8efb2be85/src/sanitize.ts
|
|
183
223
|
*/
|
|
184
224
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
225
|
+
* Returns a deep structural copy of `obj` with prototype-pollution vectors
|
|
226
|
+
* stripped at every level (`__proto__`, `prototype`, `constructor`).
|
|
227
|
+
*
|
|
228
|
+
* The input is never modified. Arrays are copied element-by-element;
|
|
229
|
+
* nested objects are recursed with a WeakSet cycle guard.
|
|
188
230
|
*/
|
|
189
231
|
function sanitizeObject(obj) {
|
|
190
232
|
if (!obj || typeof obj !== "object") return obj;
|
|
191
|
-
|
|
192
|
-
return obj;
|
|
233
|
+
return _sanitizeCopy(obj, /* @__PURE__ */ new WeakSet());
|
|
193
234
|
}
|
|
194
|
-
function
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (!seen.has(v)) {
|
|
202
|
-
seen.add(v);
|
|
203
|
-
sanitizeKeys(v, seen);
|
|
204
|
-
}
|
|
235
|
+
function _sanitizeCopy(current, seen) {
|
|
236
|
+
seen.add(current);
|
|
237
|
+
if (Array.isArray(current)) return current.map((item) => item && typeof item === "object" && !seen.has(item) ? _sanitizeCopy(item, seen) : item);
|
|
238
|
+
const result = {};
|
|
239
|
+
for (const [key, value] of Object.entries(current)) {
|
|
240
|
+
if (key === "__proto__" || key === "prototype" || key === "constructor") continue;
|
|
241
|
+
result[key] = value && typeof value === "object" && !seen.has(value) ? _sanitizeCopy(value, seen) : value;
|
|
205
242
|
}
|
|
243
|
+
return result;
|
|
206
244
|
}
|
|
207
245
|
//#endregion
|
|
208
246
|
//#region src/core/utils/index.ts
|
|
209
|
-
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
210
|
-
applyTypCtyDefaults: () => applyTypCtyDefaults,
|
|
211
|
-
assertCryptoKey: () => assertCryptoKey,
|
|
212
|
-
base64Decode: () => base64Decode,
|
|
213
|
-
base64Encode: () => base64Encode,
|
|
214
|
-
base64UrlDecode: () => base64UrlDecode,
|
|
215
|
-
base64UrlEncode: () => base64UrlEncode,
|
|
216
|
-
computeExpiresInSeconds: () => computeExpiresInSeconds,
|
|
217
|
-
computeJwtTimeClaims: () => computeJwtTimeClaims,
|
|
218
|
-
computeMaxTokenAgeSeconds: () => computeMaxTokenAgeSeconds,
|
|
219
|
-
concatUint8Arrays: () => concatUint8Arrays,
|
|
220
|
-
decodeMaybeJWTString: () => decodeMaybeJWTString,
|
|
221
|
-
decodePayloadFromB64UrlSegment: () => decodePayloadFromB64UrlSegment,
|
|
222
|
-
decodePayloadFromBytes: () => decodePayloadFromBytes,
|
|
223
|
-
getPlaintextBytes: () => getPlaintextBytes,
|
|
224
|
-
isAsymmetricJWK: () => isAsymmetricJWK,
|
|
225
|
-
isCryptoKey: () => isCryptoKey,
|
|
226
|
-
isCryptoKeyPair: () => isCryptoKeyPair,
|
|
227
|
-
isJWK: () => isJWK,
|
|
228
|
-
isJWKSet: () => isJWKSet,
|
|
229
|
-
isJWTContent: () => isJWTContent,
|
|
230
|
-
isPrivateJWK: () => isPrivateJWK,
|
|
231
|
-
isPublicJWK: () => isPublicJWK,
|
|
232
|
-
isSymmetricJWK: () => isSymmetricJWK,
|
|
233
|
-
maybeArray: () => maybeArray,
|
|
234
|
-
randomBytes: () => randomBytes,
|
|
235
|
-
sanitizeObject: () => sanitizeObject,
|
|
236
|
-
textDecoder: () => textDecoder,
|
|
237
|
-
textEncoder: () => textEncoder,
|
|
238
|
-
validateCriticalHeadersJWE: () => validateCriticalHeadersJWE,
|
|
239
|
-
validateCriticalHeadersJWS: () => validateCriticalHeadersJWS,
|
|
240
|
-
validateJwtClaims: () => validateJwtClaims
|
|
241
|
-
});
|
|
242
247
|
const textEncoder = /* @__PURE__ */ new TextEncoder();
|
|
243
248
|
const textDecoder = /* @__PURE__ */ new TextDecoder();
|
|
244
249
|
const _Buffer = /* @__PURE__ */ (() => {
|
|
@@ -371,4 +376,4 @@ function isPublicJWK(key) {
|
|
|
371
376
|
return false;
|
|
372
377
|
}
|
|
373
378
|
//#endregion
|
|
374
|
-
export {
|
|
379
|
+
export { validateCriticalHeadersJWS as A, computeMaxTokenAgeSeconds as C, getPlaintextBytes as D, decodePayloadFromBytes as E, JWTError as M, isJWTError as N, isJWTContent as O, computeJwtTimeClaims as S, decodePayloadFromB64UrlSegment as T, textDecoder as _, base64UrlEncode as a, applyTypCtyDefaults as b, isCryptoKey as c, isJWKSet as d, isPrivateJWK as f, randomBytes as g, maybeArray as h, base64UrlDecode as i, validateJwtClaims as j, validateCriticalHeadersJWE as k, isCryptoKeyPair as l, isSymmetricJWK as m, base64Decode as n, concatUint8Arrays as o, isPublicJWK as p, base64Encode as r, isAsymmetricJWK as s, assertCryptoKey as t, isJWK as u, textEncoder as v, decodeMaybeJWTString as w, computeExpiresInSeconds as x, sanitizeObject as y };
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { $ as JWK_HMAC, A as GenerateJWKReturn, B as JWKParameters, C as JWTClaims, D as DeriveKeyOptions, E as ContentEncryptionAlgorithm, F as JWKAlgorithm, G as JWK_AES_KW, H as JWK_AES_CBC_HMAC, I as JWKCacheAdapter, J as JWK_EC, K as JWK_Asymmetric, L as JWKLookupFunction, M as GenerateKeyOptions, N as GenerateKeyReturn, O as DeriveKeyReturn, P as JWK, Q as JWK_EC_Public, R as JWKLookupFunctionHeader, S as JWTClaimValidationOptions, T as CompositeKey, U as JWK_AES_GCM, V as JWKSet, W as JWK_AES_GCM_KW, X as JWK_ECDSA, Y as JWK_ECDH_ES, Z as JWK_EC_Private, _ as JWSSignOptions, _t as KeyManagementAlgorithm, a as ExpiresIn, at as JWK_Pair, b as JOSEPayload, bt as WrapKeyResult, c as JWEDecryptResult, ct as JWK_RSA, d as JWEKeyManagementHeaderParameters, dt as JWK_RSA_Private, et as JWK_OKP, f as JWEProtectedHeader, ft as JWK_RSA_Public, g as JWSProtectedHeader, gt as JWK_oct, h as JWSHeaderParameters, ht as JWK_Symmetric_Algorithm, i as importFromPEM, it as JWK_PBES2, j as GenerateKeyAlgorithm, k as GenerateJWKOptions, l as JWEEncryptOptions, lt as JWK_RSA_ENC, m as JWSAlgorithm, mt as JWK_Symmetric, n as exportToPEM, nt as JWK_OKP_Public, o as MaxTokenAge, ot as JWK_Private, p as StrictOmit, pt as JWK_RSA_SIGN, q as JWK_Asymmetric_Algorithm, r as generateJWK, rt as JWK_OKP_SIGN, s as JWEDecryptOptions, st as JWK_Public, t as deriveJWKFromPassword, tt as JWK_OKP_Private, u as JWEHeaderParameters, ut as JWK_RSA_PSS, v as JWSVerifyOptions, vt as UnwrapKeyOptions, w as JoseHeaderParameters, x as JWT, y as JWSVerifyResult, yt as WrapKeyOptions, z as JWKPEMAlgorithm } from "../../_chunks/jwk.mjs";
|
|
2
|
+
import { H3Event } from "h3";
|
|
3
|
+
import { CookieSerializeOptions } from "cookie-es";
|
|
4
|
+
|
|
5
|
+
//#region src/adapters/h3v1/session/types.d.ts
|
|
6
|
+
interface SessionClaims extends Required<Pick<JWTClaims, "jti" | "iat">>, StrictOmit<JWTClaims, "jti" | "iat"> {}
|
|
7
|
+
type SessionData<T extends Record<string, any> = SessionClaims> = StrictOmit<T, "jti" | "iat" | "exp">;
|
|
8
|
+
type SessionUpdate<T extends Record<string, any> = SessionClaims> = Partial<SessionData<T>> | ((oldData: SessionData<T>) => Partial<SessionData<T>> | undefined);
|
|
9
|
+
interface SessionManager<T extends Record<string, any> = SessionClaims, ConfigMaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
|
|
10
|
+
readonly id: string | undefined;
|
|
11
|
+
readonly createdAt: number;
|
|
12
|
+
readonly expiresAt: ConfigMaxAge extends ExpiresIn ? number : "exp" extends keyof T ? T["exp"] : number | undefined;
|
|
13
|
+
readonly data: SessionData<T>;
|
|
14
|
+
readonly token: string | undefined;
|
|
15
|
+
update: (update?: SessionUpdate<T>) => Promise<SessionManager<T, ConfigMaxAge> & {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly token: string;
|
|
18
|
+
}>;
|
|
19
|
+
clear: () => Promise<SessionManager<T, ConfigMaxAge> & {
|
|
20
|
+
readonly id: undefined;
|
|
21
|
+
readonly createdAt: number;
|
|
22
|
+
readonly expiresAt: undefined;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/adapters/h3v1/session/jwe.d.ts
|
|
27
|
+
declare const kGetSessionPromise$1: unique symbol;
|
|
28
|
+
interface SessionJWE<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
|
|
29
|
+
id: string | undefined;
|
|
30
|
+
createdAt: number;
|
|
31
|
+
expiresAt: MaxAge extends ExpiresIn ? number : T["exp"];
|
|
32
|
+
data: SessionData<T>;
|
|
33
|
+
token: string | undefined;
|
|
34
|
+
[kGetSessionPromise$1]?: Promise<SessionJWE<T, MaxAge>>;
|
|
35
|
+
}
|
|
36
|
+
interface SessionHooksJWE<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event> {
|
|
37
|
+
onRead?: (args: {
|
|
38
|
+
session: SessionJWE<T, MaxAge> & {
|
|
39
|
+
id: string;
|
|
40
|
+
token: string;
|
|
41
|
+
};
|
|
42
|
+
event: TEvent;
|
|
43
|
+
config: SessionConfigJWE<T, MaxAge, TEvent>;
|
|
44
|
+
}) => void | Promise<void>;
|
|
45
|
+
onUpdate?: (args: {
|
|
46
|
+
/** Session after it has been updated.. */session: SessionJWE<T, MaxAge> & {
|
|
47
|
+
id: string;
|
|
48
|
+
token: string;
|
|
49
|
+
}; /** Snapshot of the session before was updated. */
|
|
50
|
+
oldSession: SessionJWE<T, MaxAge>;
|
|
51
|
+
event: TEvent;
|
|
52
|
+
config: SessionConfigJWE<T, MaxAge, TEvent>;
|
|
53
|
+
}) => void | Promise<void>;
|
|
54
|
+
onClear?: (args: {
|
|
55
|
+
oldSession: SessionJWE<T, MaxAge> | undefined;
|
|
56
|
+
event: TEvent;
|
|
57
|
+
config: SessionConfigJWE<T, MaxAge, TEvent>;
|
|
58
|
+
}) => void | Promise<void>;
|
|
59
|
+
onExpire?: (args: {
|
|
60
|
+
session: {
|
|
61
|
+
id: string | undefined;
|
|
62
|
+
createdAt: number | undefined;
|
|
63
|
+
expiresAt: number | undefined;
|
|
64
|
+
token: string;
|
|
65
|
+
};
|
|
66
|
+
event: TEvent;
|
|
67
|
+
error: Error;
|
|
68
|
+
config: SessionConfigJWE<T, MaxAge, TEvent>;
|
|
69
|
+
}) => void | Promise<void>;
|
|
70
|
+
onError?: (args: {
|
|
71
|
+
/**
|
|
72
|
+
* The session involved in the error.
|
|
73
|
+
*/
|
|
74
|
+
session: SessionJWE<T, MaxAge>;
|
|
75
|
+
event: TEvent;
|
|
76
|
+
error: any;
|
|
77
|
+
config: SessionConfigJWE<T, MaxAge, TEvent>;
|
|
78
|
+
}) => void | Promise<void>;
|
|
79
|
+
onUnsealKeyLookup?: (args: {
|
|
80
|
+
header: JWEHeaderParameters;
|
|
81
|
+
event: TEvent;
|
|
82
|
+
config: SessionConfigJWE<T, MaxAge, TEvent>;
|
|
83
|
+
}) => JWK_Symmetric | JWK_Private | Promise<JWK_Symmetric | JWK_Private>;
|
|
84
|
+
}
|
|
85
|
+
interface SessionConfigJWE<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event> {
|
|
86
|
+
/** Shared key used, string for PBES2 or Json Web Key (JWK) */
|
|
87
|
+
key: string | JWK_Symmetric | JWK_Private | {
|
|
88
|
+
privateKey: JWK_Private | JWK_Symmetric;
|
|
89
|
+
publicKey?: JWK_Public;
|
|
90
|
+
};
|
|
91
|
+
/** Session lifetime in seconds (used to derive exp from iat) */
|
|
92
|
+
maxAge?: MaxAge;
|
|
93
|
+
/** Default is "h3" */
|
|
94
|
+
name?: string;
|
|
95
|
+
/** Default is secure, httpOnly, path="/" */
|
|
96
|
+
cookie?: false | CookieSerializeOptions;
|
|
97
|
+
/** Default is x-h3-session / x-{name}-session */
|
|
98
|
+
sessionHeader?: false | string;
|
|
99
|
+
/** Default is crypto.randomUUID */
|
|
100
|
+
generateId?: () => string;
|
|
101
|
+
/** JWE configuration overrides */
|
|
102
|
+
jwe?: {
|
|
103
|
+
encryptOptions?: Omit<JWEEncryptOptions, "expiresIn">;
|
|
104
|
+
decryptOptions?: JWTClaimValidationOptions;
|
|
105
|
+
};
|
|
106
|
+
hooks?: SessionHooksJWE<T, MaxAge, TEvent>;
|
|
107
|
+
}
|
|
108
|
+
type CompatEvent$1 = {
|
|
109
|
+
request: {
|
|
110
|
+
headers: Headers;
|
|
111
|
+
};
|
|
112
|
+
context: any;
|
|
113
|
+
} | {
|
|
114
|
+
headers: Headers;
|
|
115
|
+
context: any;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Create a session manager for the current request.
|
|
119
|
+
*/
|
|
120
|
+
declare function useJWESession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event>(event: TEvent, config: SessionConfigJWE<T, MaxAge, TEvent>): Promise<SessionManager<T, MaxAge>>;
|
|
121
|
+
/**
|
|
122
|
+
* Get (and lazily initialize) the session for the current request.
|
|
123
|
+
*/
|
|
124
|
+
declare function getJWESession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event>(event: TEvent, config: SessionConfigJWE<T, MaxAge, TEvent>): Promise<SessionJWE<T, MaxAge>>;
|
|
125
|
+
declare function getJWESessionToken<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event>(event: TEvent, config: SessionConfigJWE<T, MaxAge, TEvent>): string | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* Update the session (optionally mutating the session data) and re-issue the JWE token.
|
|
128
|
+
*/
|
|
129
|
+
declare function updateJWESession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event>(event: TEvent, config: SessionConfigJWE<T, MaxAge, TEvent>, update?: SessionUpdate<T>): Promise<SessionJWE<T, MaxAge> & {
|
|
130
|
+
id: string;
|
|
131
|
+
token: string;
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* Produce a JWE for the current session.
|
|
135
|
+
* Payload structure:
|
|
136
|
+
* {
|
|
137
|
+
* jti: string;
|
|
138
|
+
* iat: number; (seconds)
|
|
139
|
+
* exp?: number; (seconds)
|
|
140
|
+
* data: Record<string, any>;
|
|
141
|
+
* }
|
|
142
|
+
*/
|
|
143
|
+
declare function sealJWESession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event>(event: TEvent, config: SessionConfigJWE<T, MaxAge, TEvent>): Promise<string>;
|
|
144
|
+
/**
|
|
145
|
+
* Decrypt the JWE and return a Session-compatible object.
|
|
146
|
+
*/
|
|
147
|
+
declare function unsealJWESession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event>(event: TEvent, config: SessionConfigJWE<T, MaxAge, TEvent>, sealed: string): Promise<Partial<SessionJWE<T, MaxAge>>>;
|
|
148
|
+
/**
|
|
149
|
+
* Clear the session (delete from context and drop cookie).
|
|
150
|
+
*/
|
|
151
|
+
declare function clearJWESession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent$1 | H3Event = CompatEvent$1 | H3Event>(event: TEvent, config: SessionConfigJWE<T, MaxAge, TEvent>): Promise<void>;
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/adapters/h3v1/session/jws.d.ts
|
|
154
|
+
declare const kGetSessionPromise: unique symbol;
|
|
155
|
+
interface SessionJWS<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> {
|
|
156
|
+
id: string | undefined;
|
|
157
|
+
createdAt: number;
|
|
158
|
+
expiresAt: MaxAge extends ExpiresIn ? number : T["exp"];
|
|
159
|
+
data: SessionData<T>;
|
|
160
|
+
token: string | undefined;
|
|
161
|
+
[kGetSessionPromise]?: Promise<SessionJWS<T, MaxAge>>;
|
|
162
|
+
}
|
|
163
|
+
interface SessionHooksJWS<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event> {
|
|
164
|
+
onRead?: (args: {
|
|
165
|
+
session: SessionJWS<T, MaxAge> & {
|
|
166
|
+
id: string;
|
|
167
|
+
token: string;
|
|
168
|
+
};
|
|
169
|
+
event: TEvent;
|
|
170
|
+
config: SessionConfigJWS<T, MaxAge, TEvent>;
|
|
171
|
+
}) => void | Promise<void>;
|
|
172
|
+
onUpdate?: (args: {
|
|
173
|
+
/** Session after it has been updated.. */session: SessionJWS<T, MaxAge> & {
|
|
174
|
+
id: string;
|
|
175
|
+
token: string;
|
|
176
|
+
}; /** Snapshot of the session before was updated. */
|
|
177
|
+
oldSession: SessionJWS<T, MaxAge>;
|
|
178
|
+
event: TEvent;
|
|
179
|
+
config: SessionConfigJWS<T, MaxAge, TEvent>;
|
|
180
|
+
}) => void | Promise<void>;
|
|
181
|
+
onClear?: (args: {
|
|
182
|
+
oldSession: SessionJWS<T, MaxAge> | undefined;
|
|
183
|
+
event: TEvent;
|
|
184
|
+
config: SessionConfigJWS<T, MaxAge, TEvent>;
|
|
185
|
+
}) => void | Promise<void>;
|
|
186
|
+
onExpire?: (args: {
|
|
187
|
+
session: {
|
|
188
|
+
id: string | undefined;
|
|
189
|
+
createdAt: number | undefined;
|
|
190
|
+
expiresAt: number | undefined;
|
|
191
|
+
token: string;
|
|
192
|
+
};
|
|
193
|
+
event: TEvent;
|
|
194
|
+
error: Error;
|
|
195
|
+
config: SessionConfigJWS<T, MaxAge, TEvent>;
|
|
196
|
+
}) => void | Promise<void>;
|
|
197
|
+
onError?: (args: {
|
|
198
|
+
/**
|
|
199
|
+
* The session involved in the error.
|
|
200
|
+
*/
|
|
201
|
+
session: SessionJWS<T, MaxAge>;
|
|
202
|
+
event: TEvent;
|
|
203
|
+
error: any;
|
|
204
|
+
config: SessionConfigJWS<T, MaxAge, TEvent>;
|
|
205
|
+
}) => void | Promise<void>;
|
|
206
|
+
onVerifyKeyLookup?: (args: {
|
|
207
|
+
header: JWKLookupFunctionHeader;
|
|
208
|
+
event: TEvent;
|
|
209
|
+
config: SessionConfigJWS<T, MaxAge, TEvent>;
|
|
210
|
+
}) => JWKSet | JWK_Symmetric | JWK_Public | Promise<JWKSet | JWK_Symmetric | JWK_Public>;
|
|
211
|
+
}
|
|
212
|
+
interface SessionConfigJWS<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event> {
|
|
213
|
+
/**
|
|
214
|
+
* JWK (private for signing with RS/ES/PS, or symmetric oct) used for signing.
|
|
215
|
+
*/
|
|
216
|
+
key: JWK_Symmetric | {
|
|
217
|
+
privateKey: JWK_Private;
|
|
218
|
+
publicKey: JWK_Public | JWK_Public[] | JWKSet;
|
|
219
|
+
};
|
|
220
|
+
/** Session lifetime in seconds (sets exp = iat + maxAge) */
|
|
221
|
+
maxAge?: MaxAge;
|
|
222
|
+
/** Default cookie / header name base */
|
|
223
|
+
name?: string;
|
|
224
|
+
/** Cookie options (false to disable cookies) */
|
|
225
|
+
cookie?: false | CookieSerializeOptions;
|
|
226
|
+
/** Custom header (false to disable header lookup) */
|
|
227
|
+
sessionHeader?: false | string;
|
|
228
|
+
/** Custom ID generator (defaults to crypto.randomUUID) */
|
|
229
|
+
generateId?: () => string;
|
|
230
|
+
/** JWS customization */
|
|
231
|
+
jws?: {
|
|
232
|
+
signOptions?: Omit<JWSSignOptions, "expiresIn">;
|
|
233
|
+
verifyOptions?: JWTClaimValidationOptions;
|
|
234
|
+
};
|
|
235
|
+
hooks?: SessionHooksJWS<T, MaxAge, TEvent>;
|
|
236
|
+
}
|
|
237
|
+
type CompatEvent = {
|
|
238
|
+
request: {
|
|
239
|
+
headers: Headers;
|
|
240
|
+
};
|
|
241
|
+
context: any;
|
|
242
|
+
} | {
|
|
243
|
+
headers: Headers;
|
|
244
|
+
context: any;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Create a session manager for the current request using JWS (signed only, not encrypted).
|
|
248
|
+
* NOTE: Contents are visible to clients (Base64URL-decoded JSON). Do not store secrets in session data.
|
|
249
|
+
*/
|
|
250
|
+
declare function useJWSSession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event>(event: TEvent, config: SessionConfigJWS<T, MaxAge, TEvent>): Promise<SessionManager<T, MaxAge>>;
|
|
251
|
+
/**
|
|
252
|
+
* Retrieve (and lazily initialize) the session.
|
|
253
|
+
*/
|
|
254
|
+
declare function getJWSSession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event>(event: TEvent, config: SessionConfigJWS<T, MaxAge, TEvent>): Promise<SessionJWS<T, MaxAge>>;
|
|
255
|
+
/**
|
|
256
|
+
* Update session data (if provided) and reissue JWS.
|
|
257
|
+
*/
|
|
258
|
+
declare function updateJWSSession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event>(event: TEvent, config: SessionConfigJWS<T, MaxAge, TEvent>, update?: SessionUpdate<T>): Promise<SessionJWS<T, MaxAge> & {
|
|
259
|
+
id: string;
|
|
260
|
+
token: string;
|
|
261
|
+
}>;
|
|
262
|
+
/**
|
|
263
|
+
* Sign current session as a compact JWS.
|
|
264
|
+
* Payload claims:
|
|
265
|
+
* jti, iat, exp?, data, plus optional extraClaims (cannot override reserved)
|
|
266
|
+
*/
|
|
267
|
+
declare function signJWSSession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event>(event: TEvent, config: SessionConfigJWS<T, MaxAge, TEvent>): Promise<string>;
|
|
268
|
+
/**
|
|
269
|
+
* Verify and parse a compact JWS into a Session structure.
|
|
270
|
+
* Performs:
|
|
271
|
+
* - cryptographic signature verification
|
|
272
|
+
* - (optional) standard claim checks if validateJWT true
|
|
273
|
+
* - ensures jti & iat presence
|
|
274
|
+
* - enforces maxAge if provided
|
|
275
|
+
*/
|
|
276
|
+
declare function verifyJWSSession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event>(event: TEvent, config: SessionConfigJWS<T, MaxAge, TEvent>, token: string): Promise<Partial<SessionJWS<T, MaxAge>>>;
|
|
277
|
+
/**
|
|
278
|
+
* Destroy the session (context + cookie).
|
|
279
|
+
*/
|
|
280
|
+
declare function clearJWSSession<T extends Record<string, any> = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent extends CompatEvent | H3Event = CompatEvent | H3Event>(event: TEvent, config: SessionConfigJWS<T, MaxAge, TEvent>): Promise<void>;
|
|
281
|
+
//#endregion
|
|
282
|
+
export { CompositeKey, ContentEncryptionAlgorithm, DeriveKeyOptions, DeriveKeyReturn, ExpiresIn, GenerateJWKOptions, GenerateJWKReturn, GenerateKeyAlgorithm, GenerateKeyOptions, GenerateKeyReturn, JOSEPayload, JWEDecryptOptions, JWEDecryptResult, JWEEncryptOptions, JWEHeaderParameters, JWEKeyManagementHeaderParameters, JWEProtectedHeader, JWK, JWKAlgorithm, JWKCacheAdapter, JWKLookupFunction, JWKLookupFunctionHeader, JWKPEMAlgorithm, JWKParameters, JWKSet, 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, JWSHeaderParameters, JWSProtectedHeader, JWSSignOptions, JWSVerifyOptions, JWSVerifyResult, JWT, JWTClaimValidationOptions, JWTClaims, JoseHeaderParameters, KeyManagementAlgorithm, MaxTokenAge, type SessionClaims, type SessionConfigJWE, type SessionConfigJWS, type SessionData, type SessionHooksJWE, type SessionHooksJWS, type SessionJWE, type SessionJWS, type SessionManager, type SessionUpdate, UnwrapKeyOptions, WrapKeyOptions, WrapKeyResult, clearJWESession, clearJWSSession, deriveJWKFromPassword, exportToPEM, generateJWK, getJWESession, getJWESessionToken, getJWSSession, importFromPEM, sealJWESession, signJWSSession, unsealJWESession, updateJWESession, updateJWSSession, useJWESession, useJWSSession, verifyJWSSession };
|