@btravstack/http-server / oidc
oidc
Classes
OidcUnreachable
Defined in: packages/http-server/src/oidc.ts:39
Discovery did not answer, at boot. cause is whatever openid-client rejected with — a connection refused, a document that is not one, a 404 on .well-known — kept whole rather than flattened to a message, since the three read very differently to whoever is fixing the deployment.
Extends
TaggedErrorInstance<"OidcUnreachable", {cause:unknown;issuer:string; }>
Constructors
Constructor
new OidcUnreachable(args): OidcUnreachable;Defined in: node_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2034
Parameters
| Parameter | Type |
|---|---|
args | object & object |
Returns
Inherited from
TaggedError("OidcUnreachable")<{
readonly issuer: string;
readonly cause: unknown;
}>.constructorProperties
| Property | Modifier | Type | Inherited from | Defined in |
|---|---|---|---|---|
_tag | readonly | "OidcUnreachable" | TaggedError("OidcUnreachable")._tag | node_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2011 |
cause | public | unknown | UnderScoped.cause | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24 |
issuer | readonly | string | TaggedError("OidcUnreachable").issuer | packages/http-server/src/oidc.ts:40 |
message | public | string | TaggedError("OidcUnreachable").message | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075 |
name | public | string | TaggedError("OidcUnreachable").name | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074 |
stack? | public | string | TaggedError("OidcUnreachable").stack | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076 |
Type Aliases
OidcOptions
type OidcOptions<P> = object;Defined in: packages/http-server/src/oidc.ts:57
Type Parameters
| Type Parameter |
|---|
P |
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
allowInsecureIssuer? | readonly | boolean | Talk to an http: issuer that is NOT on a loopback host. Default false, and a ConfigInvalid at boot without it: the client secret, the code and every token cross the wire in cleartext, and allowInsecureRequests turns off the check that would have said so. An OPTION rather than a variable, on rule 6's own test: its silent change is a security regression, which is the argument securityHeaders is an option for. A loopback issuer — localhost, 127.0.0.1, [::1] — needs nothing, because plaintext that never leaves the machine is the dev loop's own Ory. | packages/http-server/src/oidc.ts:98 |
clientId? | readonly | string | Pins HTTP_OIDC_CLIENT_ID. | packages/http-server/src/oidc.ts:61 |
clientSecret? | readonly | string | Pins HTTP_OIDC_CLIENT_SECRET — this is a confidential client. | packages/http-server/src/oidc.ts:63 |
issuer? | readonly | string | Pins HTTP_OIDC_ISSUER — the provider, as its discovery document names itself. | packages/http-server/src/oidc.ts:59 |
postLogout? | readonly | `/${string}` | Where a logout lands when the provider advertises no end_session_endpoint. Default /. | packages/http-server/src/oidc.ts:85 |
prefix? | readonly | `/${string}` | Where the three routes are mounted. Default /auth. | packages/http-server/src/oidc.ts:71 |
principal | readonly | (claims) => P | undefined | What the ID token's claims make the caller — the same shape jwtAuthenticator takes, so one function serves both. Answering undefined refuses the login: the claim this application requires and the standard does not, such as a tenant. | packages/http-server/src/oidc.ts:80 |
redirectUri? | readonly | string | Pins HTTP_OIDC_REDIRECT_URI — the URI REGISTERED with the provider, which is also what the code grant is checked against. It is never rebuilt from the request's Host. | packages/http-server/src/oidc.ts:69 |
scope? | readonly | string | What the authorization request asks for. Default openid. | packages/http-server/src/oidc.ts:73 |
Functions
oidc()
function oidc<P>(options): Provider<HttpHandler, OidcUnreachable | ConfigInvalid, Env | SessionCodec | Observers> & object;Defined in: packages/http-server/src/oidc.ts:443
The login answerer: three routes that log a browser in over the authorization-code flow with PKCE and hand the result to SessionCodec as a session cookie.
export const BrowserApi = HttpModule("BrowserApi")({
fragments,
fragmentsLogin: "/auth/login",
provides: [sessionCodec(), oidc({ principal: identityOf })],
});GET <prefix>/login?return=<path>&as=<hint>seals a PKCE verifier,state,nonceand where to return to into the five-minute__Host-oidccookie and redirects to the provider.returnis the seamhtmx({ login })writes;asrides through aslogin_hint.GET <prefix>/callbackchecksstateagainst that cookie, exchanges the code, and sealsprincipal(claims)into__Host-session— clearing the transient in the same answer.POST <prefix>/logoutclears the session and sends the browser to the provider'send_session_endpoint, or topostLogoutwhen it advertises none.
Each of the three routes is an OPERATION reported to Observers, the way a cache read is: a refusal settles error carrying its own reason, so a rotated client secret is one dimension rather than an indistinguishable spike of bad logins. It costs a root nothing — httpServer already contributes the no-op member — and a root composing observability() gets the line for free.
It injects SessionCodec rather than holding keys, so the codec that seals a session here is the one sessionAuthenticator reads it back with — and a root composing this without sessionCodec() is di's own unmet need naming the port.
Type Parameters
| Type Parameter |
|---|
P |
Parameters
| Parameter | Type |
|---|---|
options | OidcOptions<P> |
Returns
Provider<HttpHandler, OidcUnreachable | ConfigInvalid, Env | SessionCodec | Observers> & object