unjwt 0.9.0 → 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.
- package/dist/session/index.d.mts +157 -24
- package/dist/session/index.mjs +129 -119
- package/package.json +1 -1
package/dist/session/index.d.mts
CHANGED
|
@@ -200,7 +200,7 @@ interface SessionRequestBase {
|
|
|
200
200
|
readonly headers: Headers;
|
|
201
201
|
readonly errHeaders?: Headers;
|
|
202
202
|
};
|
|
203
|
-
/** Per-request state shared with the framework. Sessions are stored in its `
|
|
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
204
|
readonly context?: Record<string, unknown>;
|
|
205
205
|
}
|
|
206
206
|
/** A request event, by its `Request` or by its `Headers` (a `Request` itself, a WebSocket upgrade request). `req` is read first. */
|
|
@@ -261,6 +261,91 @@ interface SessionDriver<TEvent> {
|
|
|
261
261
|
token: string | undefined;
|
|
262
262
|
} | undefined;
|
|
263
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;
|
|
264
349
|
/**
|
|
265
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
|
|
266
351
|
* without `alg`) verifies, and with `onKeyLookup` set, may also name those only the keys it returns serve. The session sets `typ`,
|
|
@@ -292,27 +377,6 @@ interface JWSSessionConfig<MaxAge extends ExpiresIn | undefined = ExpiresIn | un
|
|
|
292
377
|
*/
|
|
293
378
|
jws?: JWSSessionOptions;
|
|
294
379
|
}
|
|
295
|
-
/** The `Set-Cookie` attributes of a session cookie (RFC 6265, RFC 6265bis, and CHIPS: Cookies Having Independent Partitioned State). */
|
|
296
|
-
interface CookieAttributes {
|
|
297
|
-
/** `Domain`. A `__Host-` name refuses it. */
|
|
298
|
-
domain?: string;
|
|
299
|
-
/** `Expires`. An issued token with an `exp` sets it to that time. */
|
|
300
|
-
expires?: Date;
|
|
301
|
-
/** `HttpOnly`: page scripts cannot read the cookie. */
|
|
302
|
-
httpOnly?: boolean;
|
|
303
|
-
/** `Max-Age` in seconds. An issued token with an `exp` replaces it with `expires`. */
|
|
304
|
-
maxAge?: number;
|
|
305
|
-
/** `Path`. A `__Host-` name requires `"/"`. */
|
|
306
|
-
path?: string;
|
|
307
|
-
/** `Priority`. */
|
|
308
|
-
priority?: "low" | "medium" | "high";
|
|
309
|
-
/** `SameSite`. `true` is `Strict`, and `"none"` requires `secure`. */
|
|
310
|
-
sameSite?: boolean | "lax" | "strict" | "none";
|
|
311
|
-
/** `Secure`. A `__Host-` or `__Secure-` name requires it. */
|
|
312
|
-
secure?: boolean;
|
|
313
|
-
/** `Partitioned` (CHIPS). Requires `secure`. */
|
|
314
|
-
partitioned?: boolean;
|
|
315
|
-
}
|
|
316
380
|
/** Session state for the current request, from the claims of its JWS token. */
|
|
317
381
|
interface SessionJWS<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined> extends SessionState<T, MaxAge> {}
|
|
318
382
|
/** JWS session hooks. `onRead`, `onExpire` and `onError` are mutually exclusive per token. */
|
|
@@ -452,6 +516,75 @@ export declare function defineJWESession<T extends SessionRecord = SessionClaims
|
|
|
452
516
|
export declare function defineJWESession<T extends SessionRecord = SessionClaims, MaxAge extends ExpiresIn | undefined = ExpiresIn | undefined, TEvent = WebSessionEvent>(config: SessionConfigJWE<T, MaxAge, TEvent>, options: {
|
|
453
517
|
driver: SessionDriver<TEvent>;
|
|
454
518
|
}): SessionDefinition<T, MaxAge, TEvent>;
|
|
455
|
-
/**
|
|
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
|
+
*/
|
|
456
523
|
export declare function defineSessionDriver<TEvent>(driver: SessionDriver<TEvent>): SessionDriver<TEvent>;
|
|
457
|
-
|
|
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 };
|
package/dist/session/index.mjs
CHANGED
|
@@ -47,6 +47,9 @@ function expiredSessionError(options) {
|
|
|
47
47
|
function readFailedError(cause, options) {
|
|
48
48
|
return new JWTError(`${options.prefix} Session could not be read: ${messageOf(cause)}`, "ERR_SESSION_READ_FAILED", cause);
|
|
49
49
|
}
|
|
50
|
+
function malformedHeaderError(header, options) {
|
|
51
|
+
return invalidTokenError(`${options.prefix} Invalid session token: the "${header}" header holds neither a token nor "Bearer <token>".`);
|
|
52
|
+
}
|
|
50
53
|
function rethrowAsInvalidToken(error, options) {
|
|
51
54
|
if (isJWTError(error, "ERR_JWT_EXPIRED") || isJWTError(error, "ERR_SESSION_READ_FAILED")) throw error;
|
|
52
55
|
throw invalidTokenError(`${options.prefix} Invalid session token: ${messageOf(error)}`, error);
|
|
@@ -65,7 +68,7 @@ function assertCookiePrefix(name, attrs, options) {
|
|
|
65
68
|
const host = lower.startsWith("__host-");
|
|
66
69
|
if (!host && !lower.startsWith("__secure-")) return;
|
|
67
70
|
const rule = host ? "\"__Host-\" cookie must be Secure, with Path=/ and no Domain" : "\"__Secure-\" cookie must be Secure";
|
|
68
|
-
if (attrs.secure
|
|
71
|
+
if (!attrs.secure || host && (attrs.domain !== void 0 || attrs.path !== void 0 && attrs.path !== "/")) throw invalidConfigError(`${options.prefix} Session ${quoteTokenValue(name)}: a ${rule}.`);
|
|
69
72
|
}
|
|
70
73
|
function assertRolling(config, options) {
|
|
71
74
|
const { rolling } = config;
|
|
@@ -161,7 +164,6 @@ function createSessionCodec(spec) {
|
|
|
161
164
|
return {
|
|
162
165
|
family: spec.family,
|
|
163
166
|
defaultName: spec.defaultName,
|
|
164
|
-
defaultCookie: spec.defaultCookie,
|
|
165
167
|
now,
|
|
166
168
|
keys: (config) => {
|
|
167
169
|
const { issueKey, issueAlg, key, algorithms } = spec.resolveKeys(config);
|
|
@@ -503,19 +505,12 @@ const RSA_SIGNATURES = [
|
|
|
503
505
|
"PS384",
|
|
504
506
|
"PS512"
|
|
505
507
|
];
|
|
506
|
-
const JWS_DEFAULT_COOKIE = {
|
|
507
|
-
path: "/",
|
|
508
|
-
secure: true,
|
|
509
|
-
httpOnly: true,
|
|
510
|
-
sameSite: "lax"
|
|
511
|
-
};
|
|
512
508
|
function createJWSCodec(options) {
|
|
513
509
|
const { prefix, defaultName } = options;
|
|
514
510
|
return createSessionCodec({
|
|
515
511
|
family: "jws",
|
|
516
512
|
prefix,
|
|
517
513
|
defaultName,
|
|
518
|
-
defaultCookie: JWS_DEFAULT_COOKIE,
|
|
519
514
|
issueOptions: (config) => config.jws?.signOptions,
|
|
520
515
|
openOptions: (config) => config.jws?.verifyOptions,
|
|
521
516
|
resolveKeys: (config) => resolveSessionKeys$1(config.key, {
|
|
@@ -543,6 +538,12 @@ function createJWSCodec(options) {
|
|
|
543
538
|
}
|
|
544
539
|
});
|
|
545
540
|
}
|
|
541
|
+
const DEFAULT_SESSION_COOKIE = /* @__PURE__ */ Object.freeze({
|
|
542
|
+
path: "/",
|
|
543
|
+
secure: true,
|
|
544
|
+
httpOnly: true,
|
|
545
|
+
sameSite: "lax"
|
|
546
|
+
});
|
|
546
547
|
const kSessionPending = Symbol("unjwt_session_pending");
|
|
547
548
|
function sessionInstant(source) {
|
|
548
549
|
const now = source.codec.now(source.config);
|
|
@@ -674,7 +675,7 @@ function decodeValue(value) {
|
|
|
674
675
|
return value;
|
|
675
676
|
}
|
|
676
677
|
}
|
|
677
|
-
function
|
|
678
|
+
function resolveSessionTransport(driver, event, options) {
|
|
678
679
|
const handed = driver.handed?.(event);
|
|
679
680
|
if (handed) return {
|
|
680
681
|
source: "token",
|
|
@@ -682,11 +683,11 @@ function resolveTransport(driver, event, options) {
|
|
|
682
683
|
readonly: false,
|
|
683
684
|
writable: () => true
|
|
684
685
|
};
|
|
685
|
-
const {
|
|
686
|
+
const { name, cookie } = options;
|
|
686
687
|
const header = presentedHeader(driver, event, options);
|
|
687
|
-
if (
|
|
688
|
+
if (cookie === false) return headerTransport(options, header);
|
|
688
689
|
const jar = driver.cookies(event);
|
|
689
|
-
if (header && (header.token === void 0 || header.token !== readChunked(jar, name))) return headerTransport(
|
|
690
|
+
if (header && (header.token === void 0 || header.token !== readChunked(jar, name))) return headerTransport(options, header);
|
|
690
691
|
const store = responseStore(jar);
|
|
691
692
|
const transport = {
|
|
692
693
|
source: "cookie",
|
|
@@ -695,22 +696,32 @@ function resolveTransport(driver, event, options) {
|
|
|
695
696
|
writable: () => driver.writable?.(event) ?? true
|
|
696
697
|
};
|
|
697
698
|
if (!store) return transport;
|
|
698
|
-
|
|
699
|
+
const { attrs, chunkMaxLength } = cookie;
|
|
700
|
+
transport.write = (token, { expiresAt } = {}) => {
|
|
701
|
+
if (!transport.writable()) return false;
|
|
702
|
+
const written = expiresAt === void 0 ? { ...attrs } : {
|
|
703
|
+
...attrs,
|
|
704
|
+
expires: new Date(expiresAt),
|
|
705
|
+
maxAge: void 0
|
|
706
|
+
};
|
|
699
707
|
writeChunked(store, name, token, {
|
|
700
|
-
attrs,
|
|
708
|
+
attrs: written,
|
|
701
709
|
chunkMaxLength,
|
|
702
710
|
prefix: driver.prefix
|
|
703
711
|
});
|
|
712
|
+
return true;
|
|
704
713
|
};
|
|
705
|
-
transport.drop = (
|
|
714
|
+
transport.drop = () => {
|
|
715
|
+
if (!transport.writable()) return false;
|
|
706
716
|
removeChunked(store, name, { attrs });
|
|
717
|
+
return true;
|
|
707
718
|
};
|
|
708
719
|
return transport;
|
|
709
720
|
}
|
|
710
|
-
function
|
|
721
|
+
function assertSessionTokenSource(transport, options) {
|
|
711
722
|
if (!transport.read) throw invalidConfigError(`${options.prefix} Session has no token source, enable "cookie" or "sessionHeader".`);
|
|
712
723
|
}
|
|
713
|
-
function
|
|
724
|
+
function assertSessionWritable(transport, options) {
|
|
714
725
|
const { operation, prefix } = options;
|
|
715
726
|
if (operation === "update" && transport.readonly) throw readOnlyEventError(`${prefix} Cannot update session on read-only event.`);
|
|
716
727
|
if (!transport.writable()) throw readOnlyEventError(`${prefix} Cannot update/clear session: the response was already sent.`);
|
|
@@ -732,29 +743,29 @@ function headerToken(value) {
|
|
|
732
743
|
return words.length === 1 && first ? first : void 0;
|
|
733
744
|
}
|
|
734
745
|
function presentedHeader(driver, event, options) {
|
|
735
|
-
const {
|
|
736
|
-
if (!readsHeader(
|
|
737
|
-
const header = sessionHeaderName(name,
|
|
746
|
+
const { name, sessionHeader } = options;
|
|
747
|
+
if (!readsHeader(options)) return void 0;
|
|
748
|
+
const header = sessionHeaderName(name, sessionHeader);
|
|
738
749
|
const value = driver.header(event, header);
|
|
739
750
|
if (typeof value !== "string") return void 0;
|
|
740
751
|
const token = headerToken(value);
|
|
741
752
|
if (token) return { token };
|
|
742
753
|
return {
|
|
743
754
|
token: void 0,
|
|
744
|
-
malformed:
|
|
755
|
+
malformed: { header }
|
|
745
756
|
};
|
|
746
757
|
}
|
|
747
|
-
function headerTransport(
|
|
758
|
+
function headerTransport(options, header) {
|
|
748
759
|
return {
|
|
749
760
|
source: "header",
|
|
750
|
-
read: readsHeader(
|
|
761
|
+
read: readsHeader(options) ? () => header?.token : void 0,
|
|
751
762
|
malformed: header?.malformed,
|
|
752
763
|
readonly: false,
|
|
753
764
|
writable: () => true
|
|
754
765
|
};
|
|
755
766
|
}
|
|
756
|
-
function readsHeader(
|
|
757
|
-
return
|
|
767
|
+
function readsHeader(options) {
|
|
768
|
+
return options.sessionHeader !== void 0 && options.sessionHeader !== false;
|
|
758
769
|
}
|
|
759
770
|
function cookieToken(jar, name) {
|
|
760
771
|
const written = jar.written ? readChunked({ read: (key) => jar.written?.(key) }, name) : void 0;
|
|
@@ -772,15 +783,48 @@ function responseStore(jar) {
|
|
|
772
783
|
const kSessionNames = Symbol("unjwt_session_names");
|
|
773
784
|
const kHeldTokens = Symbol("unjwt_session_held_tokens");
|
|
774
785
|
function assertSessionConfig(config, options) {
|
|
775
|
-
const { name, prefix } = options;
|
|
786
|
+
const { name, prefix, defaultCookie = DEFAULT_SESSION_COOKIE } = options;
|
|
776
787
|
assertSessionName(name, { prefix });
|
|
777
788
|
assertSessionHeader(config.sessionHeader, { prefix });
|
|
778
789
|
if (config.cookie !== false) assertCookiePrefix(name, {
|
|
779
|
-
...
|
|
790
|
+
...defaultCookie,
|
|
780
791
|
...config.cookie
|
|
781
792
|
}, { prefix });
|
|
782
793
|
assertRolling(config, { prefix });
|
|
783
794
|
}
|
|
795
|
+
function sessionTransportOptions(config, options) {
|
|
796
|
+
const { name, defaultCookie = DEFAULT_SESSION_COOKIE } = options;
|
|
797
|
+
const { sessionHeader } = config;
|
|
798
|
+
if (config.cookie === false) return {
|
|
799
|
+
name,
|
|
800
|
+
sessionHeader,
|
|
801
|
+
cookie: false
|
|
802
|
+
};
|
|
803
|
+
const { chunkMaxLength, ...configured } = config.cookie || {};
|
|
804
|
+
return {
|
|
805
|
+
name,
|
|
806
|
+
sessionHeader,
|
|
807
|
+
cookie: {
|
|
808
|
+
attrs: {
|
|
809
|
+
...defaultCookie,
|
|
810
|
+
...configured
|
|
811
|
+
},
|
|
812
|
+
chunkMaxLength
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
function claimSessionName(state, options) {
|
|
817
|
+
const { name, family, prefix } = options;
|
|
818
|
+
const holder = state;
|
|
819
|
+
const registry = holder[kSessionNames] ||= /* @__PURE__ */ new Map();
|
|
820
|
+
const held = registry.get(name);
|
|
821
|
+
if (held === void 0) {
|
|
822
|
+
registry.set(name, family);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
if (held === family) return;
|
|
826
|
+
throw invalidConfigError(`${prefix} Session name "${name}" is already used by a ${held.toUpperCase()} session on this request.`);
|
|
827
|
+
}
|
|
784
828
|
function bindSession(event, options) {
|
|
785
829
|
const { config, name, driver, codec, keys, actions } = options;
|
|
786
830
|
const record = driver.state(event);
|
|
@@ -801,21 +845,18 @@ function bindSession(event, options) {
|
|
|
801
845
|
args: { event },
|
|
802
846
|
store: recordSlotStore(record, slot),
|
|
803
847
|
held: heldTokenSlot(record, slot),
|
|
804
|
-
transport:
|
|
805
|
-
config,
|
|
806
|
-
name
|
|
807
|
-
})
|
|
848
|
+
transport: resolveSessionTransport(driver, event, sessionTransportOptions(config, { name }))
|
|
808
849
|
};
|
|
809
850
|
}
|
|
810
851
|
function sessionToken(binding) {
|
|
811
852
|
const { transport } = binding;
|
|
812
|
-
|
|
853
|
+
assertSessionTokenSource(transport, { prefix: binding.driver.prefix });
|
|
813
854
|
const session = storedSession(binding.store);
|
|
814
855
|
return session ? session.token : transport.read();
|
|
815
856
|
}
|
|
816
857
|
function transportToken(binding) {
|
|
817
858
|
const { transport } = binding;
|
|
818
|
-
|
|
859
|
+
assertSessionTokenSource(transport, { prefix: binding.driver.prefix });
|
|
819
860
|
const held = binding.held.get();
|
|
820
861
|
return held ? held.token : transport.read();
|
|
821
862
|
}
|
|
@@ -827,38 +868,6 @@ function recordSlotStore(record, slot) {
|
|
|
827
868
|
}
|
|
828
869
|
};
|
|
829
870
|
}
|
|
830
|
-
function sessionCookie(binding, options = {}) {
|
|
831
|
-
const { chunkMaxLength, ...configured } = binding.config.cookie || {};
|
|
832
|
-
const attrs = {
|
|
833
|
-
...binding.codec.defaultCookie,
|
|
834
|
-
...configured
|
|
835
|
-
};
|
|
836
|
-
if (options.expiresAt !== void 0) {
|
|
837
|
-
attrs.expires = new Date(options.expiresAt);
|
|
838
|
-
attrs.maxAge = void 0;
|
|
839
|
-
}
|
|
840
|
-
return {
|
|
841
|
-
attrs,
|
|
842
|
-
chunkMaxLength
|
|
843
|
-
};
|
|
844
|
-
}
|
|
845
|
-
function dropSessionCookie(binding) {
|
|
846
|
-
const { transport } = binding;
|
|
847
|
-
if (!transport.drop || !transport.writable()) return;
|
|
848
|
-
transport.drop(sessionCookie(binding));
|
|
849
|
-
}
|
|
850
|
-
function claimSessionName(record, options) {
|
|
851
|
-
const { name, family, prefix } = options;
|
|
852
|
-
const holder = record;
|
|
853
|
-
const registry = holder[kSessionNames] ||= /* @__PURE__ */ new Map();
|
|
854
|
-
const held = registry.get(name);
|
|
855
|
-
if (held === void 0) {
|
|
856
|
-
registry.set(name, family);
|
|
857
|
-
return;
|
|
858
|
-
}
|
|
859
|
-
if (held === family) return;
|
|
860
|
-
throw invalidConfigError(`${prefix} Session name "${name}" is already used by a ${held.toUpperCase()} session on this request.`);
|
|
861
|
-
}
|
|
862
871
|
function heldTokenSlot(record, slot) {
|
|
863
872
|
const holder = record;
|
|
864
873
|
const held = holder[kHeldTokens] ||= /* @__PURE__ */ new Map();
|
|
@@ -873,12 +882,12 @@ async function loadSession(binding) {
|
|
|
873
882
|
const { config, codec, keys, store, args, transport } = binding;
|
|
874
883
|
await keys.assertKeys();
|
|
875
884
|
const open = keys.opener(args);
|
|
876
|
-
|
|
885
|
+
assertSessionTokenSource(transport, { prefix: binding.driver.prefix });
|
|
877
886
|
const existing = storedSession(store);
|
|
878
887
|
if (existing) {
|
|
879
888
|
const session = existing[kSessionPending] ? await existing[kSessionPending] : existing;
|
|
880
|
-
if (session.token !== void 0 && session.expiresAt !== void 0 && session.expiresAt
|
|
881
|
-
|
|
889
|
+
if (session.token !== void 0 && session.expiresAt !== void 0 && session.expiresAt <= codec.now(config)) {
|
|
890
|
+
transport.drop?.();
|
|
882
891
|
const error = expiredSessionError({
|
|
883
892
|
id: session.id,
|
|
884
893
|
createdAt: session.createdAt,
|
|
@@ -903,8 +912,9 @@ async function loadSession(binding) {
|
|
|
903
912
|
const session = emptySession(binding);
|
|
904
913
|
store.set(session);
|
|
905
914
|
if (transport.malformed) {
|
|
906
|
-
|
|
907
|
-
|
|
915
|
+
const error = malformedHeaderError(transport.malformed.header, { prefix: binding.driver.prefix });
|
|
916
|
+
session.error = error;
|
|
917
|
+
await fireError(binding, error);
|
|
908
918
|
return session;
|
|
909
919
|
}
|
|
910
920
|
const token = transport.read();
|
|
@@ -927,7 +937,7 @@ async function loadSession(binding) {
|
|
|
927
937
|
if (isJWTError(failure.error)) session.error = failure.error;
|
|
928
938
|
if (isJWTError(failure.error, "ERR_JWT_EXPIRED")) {
|
|
929
939
|
const { jti, iat, exp } = failure.error.cause;
|
|
930
|
-
|
|
940
|
+
transport.drop?.();
|
|
931
941
|
await fireExpire(binding, {
|
|
932
942
|
session: {
|
|
933
943
|
id: jti,
|
|
@@ -938,7 +948,7 @@ async function loadSession(binding) {
|
|
|
938
948
|
error: failure.error
|
|
939
949
|
});
|
|
940
950
|
} else {
|
|
941
|
-
if (isJWTError(failure.error, "ERR_SESSION_TOKEN_INVALID"))
|
|
951
|
+
if (isJWTError(failure.error, "ERR_SESSION_TOKEN_INVALID")) transport.drop?.();
|
|
942
952
|
await fireError(binding, failure.error);
|
|
943
953
|
}
|
|
944
954
|
return session;
|
|
@@ -992,7 +1002,7 @@ async function fireExpire(binding, expired) {
|
|
|
992
1002
|
}
|
|
993
1003
|
async function issueSession(binding, update, options, trigger = "update") {
|
|
994
1004
|
const { config, keys, driver, store, args, transport } = binding;
|
|
995
|
-
|
|
1005
|
+
assertSessionWritable(transport, {
|
|
996
1006
|
operation: "update",
|
|
997
1007
|
prefix: driver.prefix
|
|
998
1008
|
});
|
|
@@ -1013,7 +1023,7 @@ async function issueSession(binding, update, options, trigger = "update") {
|
|
|
1013
1023
|
try {
|
|
1014
1024
|
await keys.assertKeys();
|
|
1015
1025
|
const token = await keys.issue(session);
|
|
1016
|
-
transport.write?.(token,
|
|
1026
|
+
transport.write?.(token, { expiresAt: session.expiresAt });
|
|
1017
1027
|
binding.held.set(token);
|
|
1018
1028
|
issued = Object.assign(session, {
|
|
1019
1029
|
id,
|
|
@@ -1047,8 +1057,8 @@ async function issueSession(binding, update, options, trigger = "update") {
|
|
|
1047
1057
|
}
|
|
1048
1058
|
async function dropSession(binding) {
|
|
1049
1059
|
const { config, driver, store, args, transport } = binding;
|
|
1050
|
-
|
|
1051
|
-
|
|
1060
|
+
assertSessionTokenSource(transport, { prefix: driver.prefix });
|
|
1061
|
+
assertSessionWritable(transport, {
|
|
1052
1062
|
operation: "clear",
|
|
1053
1063
|
prefix: driver.prefix
|
|
1054
1064
|
});
|
|
@@ -1057,7 +1067,7 @@ async function dropSession(binding) {
|
|
|
1057
1067
|
const oldSession = session && (session.id !== void 0 || session.token !== void 0 || session.error !== void 0) ? snapshotSession(session) : void 0;
|
|
1058
1068
|
store.set(emptySession(binding));
|
|
1059
1069
|
binding.held.set(void 0);
|
|
1060
|
-
transport.drop?.(
|
|
1070
|
+
transport.drop?.();
|
|
1061
1071
|
await config.hooks?.onClear?.({
|
|
1062
1072
|
oldSession,
|
|
1063
1073
|
...args,
|
|
@@ -1119,8 +1129,7 @@ function defineSession(config, options) {
|
|
|
1119
1129
|
const name = config.name || codec.defaultName;
|
|
1120
1130
|
assertSessionConfig(config, {
|
|
1121
1131
|
name,
|
|
1122
|
-
prefix: driver.prefix
|
|
1123
|
-
defaultCookie: codec.defaultCookie
|
|
1132
|
+
prefix: driver.prefix
|
|
1124
1133
|
});
|
|
1125
1134
|
const keys = codec.keys(config);
|
|
1126
1135
|
const actions = sessionActions();
|
|
@@ -1163,15 +1172,15 @@ function defineSession(config, options) {
|
|
|
1163
1172
|
}
|
|
1164
1173
|
function webCookieJar(request, response) {
|
|
1165
1174
|
let cookies;
|
|
1166
|
-
const jar = { read: (name) => (cookies ||=
|
|
1175
|
+
const jar = { read: (name) => (cookies ||= parseCookie(request.get("cookie") ?? ""))[name] };
|
|
1167
1176
|
if (response) {
|
|
1168
1177
|
const { headers, errHeaders } = response;
|
|
1169
1178
|
jar.written = (name) => setCookieValues(headers.getSetCookie())[name];
|
|
1170
1179
|
jar.write = (name, value, attrs) => {
|
|
1171
1180
|
setCookie(headers, {
|
|
1181
|
+
...attrs,
|
|
1172
1182
|
name,
|
|
1173
|
-
value
|
|
1174
|
-
...attrs
|
|
1183
|
+
value
|
|
1175
1184
|
});
|
|
1176
1185
|
if (errHeaders) mirrorSetCookie(name, {
|
|
1177
1186
|
from: headers,
|
|
@@ -1181,19 +1190,24 @@ function webCookieJar(request, response) {
|
|
|
1181
1190
|
}
|
|
1182
1191
|
return jar;
|
|
1183
1192
|
}
|
|
1184
|
-
function
|
|
1185
|
-
|
|
1186
|
-
return header ? parse(header) : Object.create(null);
|
|
1193
|
+
function parseCookie(header) {
|
|
1194
|
+
return parse(header);
|
|
1187
1195
|
}
|
|
1188
|
-
function
|
|
1189
|
-
|
|
1196
|
+
function serializeCookie(name, value, attrs) {
|
|
1197
|
+
return serialize({
|
|
1190
1198
|
path: "/",
|
|
1191
|
-
...
|
|
1199
|
+
...attrs,
|
|
1200
|
+
name,
|
|
1201
|
+
value
|
|
1192
1202
|
});
|
|
1203
|
+
}
|
|
1204
|
+
function setCookie(headers, cookie) {
|
|
1205
|
+
const { name, value, ...attrs } = cookie;
|
|
1206
|
+
const line = serializeCookie(name, value, attrs);
|
|
1193
1207
|
const key = cookieKey(cookie);
|
|
1194
1208
|
const kept = headers.getSetCookie().filter((existing) => {
|
|
1195
1209
|
const parsed = parseSetCookie(existing);
|
|
1196
|
-
return parsed ? cookieKey(parsed) !== key : setCookieName(existing) !==
|
|
1210
|
+
return parsed ? cookieKey(parsed) !== key : setCookieName(existing) !== name;
|
|
1197
1211
|
});
|
|
1198
1212
|
headers.delete("set-cookie");
|
|
1199
1213
|
for (const existing of kept) headers.append("set-cookie", existing);
|
|
@@ -1208,33 +1222,36 @@ function cookieKey(cookie) {
|
|
|
1208
1222
|
cookie.partitioned ? "1" : "0"
|
|
1209
1223
|
].join(";");
|
|
1210
1224
|
}
|
|
1211
|
-
const PREFIX = "[unjwt/session]";
|
|
1212
1225
|
const requestStates = /* @__PURE__ */ new WeakMap();
|
|
1213
|
-
|
|
1214
|
-
prefix
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1226
|
+
function webSessionDriver(options) {
|
|
1227
|
+
const prefix = options?.prefix ?? "[unjwt/session]";
|
|
1228
|
+
return {
|
|
1229
|
+
prefix,
|
|
1230
|
+
state: (event) => {
|
|
1231
|
+
if (isHanded(event, prefix)) return sessionsOf(event);
|
|
1232
|
+
if (event.context) return contextState(event.context);
|
|
1233
|
+
return sessionsOf(event.req ? webRequest(event.req, prefix) : event);
|
|
1234
|
+
},
|
|
1235
|
+
header: (event, name) => isHanded(event, prefix) ? void 0 : requestHeaders(event, prefix).get(name),
|
|
1236
|
+
cookies: (event) => isHanded(event, prefix) ? { read: () => void 0 } : webCookieJar(requestHeaders(event, prefix), event.res),
|
|
1237
|
+
handed: (event) => isHanded(event, prefix) ? { token: event.token } : void 0
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
const defaultWebSessionDriver = /* @__PURE__ */ webSessionDriver();
|
|
1241
|
+
function isHanded(event, prefix) {
|
|
1225
1242
|
if ("req" in event || "headers" in event) return false;
|
|
1226
1243
|
if ("token" in event) return true;
|
|
1227
|
-
throw invalidConfigError(`${
|
|
1244
|
+
throw invalidConfigError(`${prefix} use() got neither a request event nor a token.`);
|
|
1228
1245
|
}
|
|
1229
|
-
function requestHeaders(event) {
|
|
1230
|
-
if (event.req) return webRequest(event.req).headers;
|
|
1246
|
+
function requestHeaders(event, prefix) {
|
|
1247
|
+
if (event.req) return webRequest(event.req, prefix).headers;
|
|
1231
1248
|
if (event.headers) return event.headers;
|
|
1232
|
-
throw invalidConfigError(`${
|
|
1249
|
+
throw invalidConfigError(`${prefix} use() got a request event with neither "req" nor "headers".`);
|
|
1233
1250
|
}
|
|
1234
|
-
function webRequest(req) {
|
|
1251
|
+
function webRequest(req, prefix) {
|
|
1235
1252
|
const headers = req.headers;
|
|
1236
1253
|
if (typeof headers === "object" && headers !== null && "get" in headers) return req;
|
|
1237
|
-
throw invalidConfigError(`${
|
|
1254
|
+
throw invalidConfigError(`${prefix} use() got an event whose "req" is not a web Request.`);
|
|
1238
1255
|
}
|
|
1239
1256
|
function contextState(context) {
|
|
1240
1257
|
const existing = context.unjwt;
|
|
@@ -1251,7 +1268,7 @@ function sessionsOf(request) {
|
|
|
1251
1268
|
return created;
|
|
1252
1269
|
}
|
|
1253
1270
|
function defineJWSSession(config, options) {
|
|
1254
|
-
const driver = options?.driver ??
|
|
1271
|
+
const driver = options?.driver ?? defaultWebSessionDriver;
|
|
1255
1272
|
return defineSession(config, {
|
|
1256
1273
|
driver,
|
|
1257
1274
|
codec: createJWSCodec({
|
|
@@ -1357,19 +1374,12 @@ function encryptionBits(enc) {
|
|
|
1357
1374
|
const bits = Number(enc.slice(1, 4));
|
|
1358
1375
|
return enc.includes("CBC") ? bits * 2 : bits;
|
|
1359
1376
|
}
|
|
1360
|
-
const JWE_DEFAULT_COOKIE = {
|
|
1361
|
-
path: "/",
|
|
1362
|
-
secure: true,
|
|
1363
|
-
httpOnly: true,
|
|
1364
|
-
sameSite: "lax"
|
|
1365
|
-
};
|
|
1366
1377
|
function createJWECodec(options) {
|
|
1367
1378
|
const { prefix, defaultName } = options;
|
|
1368
1379
|
return createSessionCodec({
|
|
1369
1380
|
family: "jwe",
|
|
1370
1381
|
prefix,
|
|
1371
1382
|
defaultName,
|
|
1372
|
-
defaultCookie: JWE_DEFAULT_COOKIE,
|
|
1373
1383
|
issueOptions: (config) => config.jwe?.encryptOptions,
|
|
1374
1384
|
openOptions: (config) => config.jwe?.decryptOptions,
|
|
1375
1385
|
resolveKeys: (config) => resolveSessionKeys(config.key, {
|
|
@@ -1400,7 +1410,7 @@ function sessionMaxIterations(config) {
|
|
|
1400
1410
|
return typeof alg === "string" && alg.startsWith("PBES2") ? config.jwe?.encryptOptions?.p2c ?? 6e5 : void 0;
|
|
1401
1411
|
}
|
|
1402
1412
|
function defineJWESession(config, options) {
|
|
1403
|
-
const driver = options?.driver ??
|
|
1413
|
+
const driver = options?.driver ?? defaultWebSessionDriver;
|
|
1404
1414
|
return defineSession(config, {
|
|
1405
1415
|
driver,
|
|
1406
1416
|
codec: createJWECodec({
|
|
@@ -1412,4 +1422,4 @@ function defineJWESession(config, options) {
|
|
|
1412
1422
|
function defineSessionDriver(driver) {
|
|
1413
1423
|
return driver;
|
|
1414
1424
|
}
|
|
1415
|
-
export { defineJWESession, defineJWSSession, defineSessionDriver, deriveJWKFromPassword, exportPEM, generateJWK, importPEM, thumbprint, toPublicJWK };
|
|
1425
|
+
export { DEFAULT_SESSION_COOKIE, assertSessionConfig, assertSessionHeader, assertSessionTokenSource, assertSessionWritable, claimSessionName, defineJWESession, defineJWSSession, defineSessionDriver, deriveJWKFromPassword, exportPEM, generateJWK, importPEM, parseCookie, resolveSessionTransport, serializeCookie, sessionTransportOptions, thumbprint, toPublicJWK, webCookieJar, webSessionDriver };
|