Skip to content

@btravstack/http-server


@btravstack/http-server / session

session

Classes

CookieSchemes

Defined in: packages/http-server/src/session.ts:89

One member per composed scheme, true when that scheme reads a cookie — the graph fact csrf's default is computed from. httpServer contributes the false member that keeps the set from being the empty dependency di refuses, so a graph composing no scheme at all still starts.

A set port rather than a marker HttpModule folds: http() never sees an application's authenticators — the root composes them itself — so a signal read off the options record would leave that surface silently unprotected. A ctx.get at start could not answer it either: di's Context has no has.

Extends

  • PortInstance<"HttpCookieSchemes", readonly boolean[]> & object

Constructors

Constructor
ts
new CookieSchemes(): CookieSchemes;

Defined in: packages/di/dist/index.d.mts:30

Returns

CookieSchemes

Inherited from
ts
Port.many("HttpCookieSchemes")<boolean>.constructor

Properties

PropertyModifierTypeInherited fromDefined in
[ID]readonly"HttpCookieSchemes"Port.many("HttpCookieSchemes").[ID]packages/di/dist/index.d.mts:12
[MANY]readonlytruePort.many("HttpCookieSchemes").[MANY]packages/di/dist/index.d.mts:31
[SERVICE]readonlyreadonly boolean[]Port.many("HttpCookieSchemes").[SERVICE]packages/di/dist/index.d.mts:13
manyreadonlytruePort.many("HttpCookieSchemes").manypackages/di/dist/index.d.mts:34
portIdreadonly"HttpCookieSchemes"Port.many("HttpCookieSchemes").portIdpackages/di/dist/index.d.mts:33

SessionCodec

Defined in: packages/http-server/src/session.ts:76

Extends

Constructors

Constructor
ts
new SessionCodec(): SessionCodec;

Defined in: packages/di/dist/index.d.mts:16

Returns

SessionCodec

Inherited from
ts
Port("HttpSessionCodec")<SessionCodecService>.constructor

Properties

PropertyModifierTypeInherited fromDefined in
[ID]readonly"HttpSessionCodec"Port("HttpSessionCodec").[ID]packages/di/dist/index.d.mts:12
[SERVICE]readonlySessionCodecServicePort("HttpSessionCodec").[SERVICE]packages/di/dist/index.d.mts:13
portIdreadonly"HttpSessionCodec"Port("HttpSessionCodec").portIdpackages/di/dist/index.d.mts:17

Type Aliases

Session

ts
type Session<P> = object;

Defined in: packages/http-server/src/session.ts:18

What the cookie carries: the application's own principal, and when the session ends.

The sealed payload also holds a typ marker this type does not declare — seal writes it and unseal requires it, so nothing outside this module sets or reads one. A session put back on the wire whole would carry it; send the principal, not the session.

Type Parameters

Type Parameter
P

Properties

PropertyModifierTypeDescriptionDefined in
expreadonlynumber-packages/http-server/src/session.ts:32
iatreadonlynumber-packages/http-server/src/session.ts:31
principalreadonlyP-packages/http-server/src/session.ts:19
scopes?readonlyreadonly string[]What the login recorded the session as holding. A scheme grants the INTERSECTION of its own vocabulary with this, so a session naming a scope the scheme does not know grants nothing extra.packages/http-server/src/session.ts:30
sid?readonlystringThe provider's session id, kept for logout; absent when the session was not minted by an OIDC login.packages/http-server/src/session.ts:24

SessionCodecService

ts
type SessionCodecService = object;

Defined in: packages/http-server/src/session.ts:35

Properties

PropertyModifierTypeDescriptionDefined in
sealreadonly(session) => AsyncResult<string, never>Seals a session into a JWE. iat and exp are stamped here rather than accepted, so a caller cannot mint a session that outlives the policy.packages/http-server/src/session.ts:49
transientreadonlyobjectThe login flow's own state — a PKCE verifier, state, nonce, where to return to — sealed with the SAME keys under its own purpose marker and a five-minute lifetime. A transient read as a session, or a session read as one, is undefined: the marker is what separates them. typ, iat and exp are the CODEC's: seal writes them over whatever the state carries and unseal strips them off again, so a caller's own value under one of those three names never survives the round trip — which is what stops state built from a request deciding what the payload is.packages/http-server/src/session.ts:68
transient.sealreadonly(state) => AsyncResult<string, never>-packages/http-server/src/session.ts:69
transient.unsealreadonly(cookie) => AsyncResult<Readonly<Record<string, string>> | undefined, never>-packages/http-server/src/session.ts:70
ttlSecreadonlynumberWhat seal stamps, in seconds — the whole session, since there is no sliding re-seal. It is published because a login has to write the same number into the cookie's Max-Age: a browser holding the cookie longer than the payload lives is a caller who looks anonymous with a cookie still attached, and one holding it for less is a session cut short by the wrapper rather than by the policy.packages/http-server/src/session.ts:44
unsealreadonly(cookie) => AsyncResult<Session<unknown> | undefined, never>The cookie's value, opened with whichever key still holds it. Every failure — no cookie, not a JWE, a key that is gone, a tampered ciphertext, a session past its exp — is the same undefined: an anonymous caller, never an error and never a hint about which of those it was.packages/http-server/src/session.ts:56

SessionOptions

ts
type SessionOptions<P, Scopes> = object;

Defined in: packages/http-server/src/session.ts:314

Type Parameters

Type Parameter
P
Scopes extends readonly string[]

Properties

PropertyModifierTypeDescriptionDefined in
principal?readonly(session) => P | undefinedWhat the session makes the caller. Answering undefined refuses it — the hook for a session this endpoint will not take, and the default's own answer to a session sealed with no principal at all.packages/http-server/src/session.ts:327
scopes?readonlyScopesThe scopes this scheme can grant, and the only place they are writtenjwtAuthenticator's rule, for jwtAuthenticator's reason. The grant is the INTERSECTION of this vocabulary with what the session carries. Omit it entirely for a scheme with no scopes.packages/http-server/src/session.ts:321

Variables

DEFAULT_TTL_SEC

ts
const DEFAULT_TTL_SEC: 43200 = 43_200;

Defined in: packages/http-server/src/session.ts:100

Twelve hours, fixed: there is no sliding re-seal, so this is the whole session.


ts
const SESSION_COOKIE: "__Host-session" = "__Host-session";

Defined in: packages/http-server/src/session.ts:312

The cookie the session travels on, and there is no option to rename it.

__Host- is a prefix the BROWSER enforces — Secure, Path=/, no Domain — which is the guarantee, and it is the name oidc() writes as well: the scheme that READS the cookie and the answerer that SEALS it must agree, and two options that must agree is the shape where they silently do not. One constant both name.


TRANSIENT_TTL_SEC

ts
const TRANSIENT_TTL_SEC: 300 = 300;

Defined in: packages/http-server/src/session.ts:103

Five minutes, and not an option: a login that takes longer is a login to start again.

Functions

cookieScheme()

ts
function cookieScheme(): AnyProvider;

Defined in: packages/http-server/src/session.ts:92

What defineHttp contributes for a scheme whose description says it reads a cookie.

Returns

AnyProvider


csrfOn()

ts
function csrfOn(option, schemes): boolean;

Defined in: packages/http-server/src/session.ts:96

csrf unset is on exactly when a composed scheme reads a cookie.

Parameters

ParameterType
optionboolean | undefined
schemesreadonly boolean[]

Returns

boolean


sessionAuthenticator()

ts
function sessionAuthenticator<P>(): <Scopes>(options) => Authenticator<P, Scopes[number], SessionCodec, never>;

Defined in: packages/http-server/src/session.ts:352

The session-cookie scheme: a third one beside jwtAuthenticator and apiKeyAuthenticator, so requires: [{ session: [] }] on a fragment route and authenticated({ session: [...] }) on a procedure need nothing new.

ts
export const browserAuth = sessionAuthenticator<Identity>()({ scopes: ["orders:export"] });

The cookie is SESSION_COOKIE and cannot be renamed: oidc() seals that name, so a knob here would be one half of a pair that must agree.

It injects SessionCodec rather than holding keys of its own, so a root composing this scheme without sessionCodec() is di's own unmet need naming SessionCodec — and the codec that reads a cookie is the very one that sealed it.

No cookie, a cookie no key opens, a session past its exp and a principal the application declined are ONE answer: Unauthenticated, carrying no reason, which is the codec's own rule one layer up.

Type Parameters

Type Parameter
P

Returns

<Scopes>(options) => Authenticator<P, Scopes[number], SessionCodec, never>


sessionCodec()

ts
function sessionCodec(pins?): Provider<SessionCodec, ConfigInvalid, Env> & object;

Defined in: packages/http-server/src/session.ts:267

The cookie codec, from HTTP_SESSION_KEYS — a comma-separated list of base64url 32-byte keys. The first seals, every one unseals, so rotation is prepend, deploy, drop; a cookie sealed with a dropped key is anonymous rather than an error.

A key that is not 32 bytes is a ConfigInvalid naming the variable, at boot, rather than a failure at the first request.

Parameters

ParameterType
pins{ keys?: readonly string[]; ttlSec?: number; }
pins.keys?readonly string[]
pins.ttlSec?number

Returns

Provider<SessionCodec, ConfigInvalid, Env> & object

Released under the MIT License.