agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
103 lines (102 loc) • 5.53 kB
TypeScript
/**
* oidcSignIn — browser sign-in for the `oidc-token` strategy: the OpenID
* Connect authorization-code flow, through `openid-client`.
*
* **Pending independent review.** The sign-in door is where the classic
* sign-in bugs live; the owner gates the release of this piece on an outside
* human security review (design Q5). It is built and tested; it is not yet
* cleared for a company install.
*
* Pattern: Adapter over `openid-client` (an OpenID-certified relying party by
* the author of `jose`), behind the door's {@link RedirectSignIn}
* port. Optional peer, loaded lazily — the `jose` precedent.
* Role: the protocol half. The sign-in door owns the cookies, `returnTo`
* and the callback order; this file builds the authorization URL and
* turns a callback into a person.
*
* ── One verification path (design §5.3, Q1) ────────────────────────────────
* The callback does NOT read the person out of the ID token. The same code
* exchange returns an ACCESS token for this API, and the strategy's own
* `verify` — the person test included — reads the person out of that. So a
* person signing in through the browser and the same person calling with a
* bearer token get the same `userId` by construction. The ID token only binds
* the login to this browser (`nonce`) and is then dropped; nothing is stored.
*
* ── What `openid-client` checks, and what this file adds ───────────────────
* `openid-client` checks `state`, the code exchange (client authentication +
* PKCE verifier), and the ID token (signature, `iss`, `aud` = the client id,
* `nonce`, `exp`, the clock tolerance). This file requires an ID token in every
* token response (with PKCE off the nonce is the only defence against an
* injected code), then runs `verify` on the access token.
*
* ── Client authentication ───────────────────────────────────────────────────
* A private key (`private_key_jwt`, RFC 7523) is preferred: nothing shared
* leaves the server. A client secret (`client_secret_basic`) is accepted —
* design §5.2: "a secret file is accepted". Exactly one of the two.
*/
import { type RedirectSignIn } from '../../hosting/signin/types.js';
import type { OidcIdentity } from './oidc.js';
/**
* The slice of `openid-client` v6 this adapter uses, declared structurally so
* the optional peer is never a hard type dependency.
*/
export interface OpenIdClientBackend {
Configuration: new (server: Record<string, unknown>, clientId: string, metadata?: Record<string, unknown>, clientAuthentication?: unknown) => unknown;
buildAuthorizationUrl(config: unknown, parameters: Record<string, string>): URL;
authorizationCodeGrant(config: unknown, currentUrl: URL, checks: Record<string, unknown>): Promise<{
access_token?: string;
id_token?: string;
}>;
buildEndSessionUrl(config: unknown, parameters: Record<string, string>): URL;
calculatePKCECodeChallenge(verifier: string): Promise<string>;
PrivateKeyJwt(key: unknown): unknown;
ClientSecretBasic(secret: string): unknown;
allowInsecureRequests(config: unknown): void;
readonly clockTolerance: symbol;
}
/** How the client authenticates at the token endpoint. */
export type OidcClientCredential = {
readonly kind: 'private-key';
readonly pem: string;
} | {
readonly kind: 'secret';
readonly secret: string;
};
export interface OidcSignInOptions {
/** The strategy's own verifier — its `verify` reads the person from the access token. */
readonly verifier: OidcIdentity;
/** The browser client's id at the IdP (never the API's audience). */
readonly clientId: string;
readonly credential: OidcClientCredential;
/** OAuth scopes to request; must include `openid` and this API's scope. */
readonly scope: string;
/** AD FS: the Web API identifier, sent as `resource` (else AD FS issues for userinfo). */
readonly resource?: string;
/** PKCE on (`'required'`, default) or off (`'off'`: AD FS 2016). */
readonly pkce?: 'required' | 'off';
/** A claim of the ACCESS token that carries the display name. */
readonly displayNameClaim?: string;
/** Seconds of clock skew for the ID token. Default 60. */
readonly clockToleranceSeconds?: number;
/** Accept `http` endpoints on a loopback host (development only). */
readonly allowLoopbackHttp?: boolean;
/** An already-imported `openid-client`. */
readonly backend?: OpenIdClientBackend;
}
/** Raised when browser sign-in is configured and `openid-client` is not installed. */
export declare class MissingOpenIdClientError extends Error {
readonly code: "ERR_MISSING_OPENID_CLIENT";
constructor();
}
/**
* A browser sign-in setting that can never work, found by `ready()` at boot —
* `setting` names which: the client key (not RSA / EC P-256, or unreadable)
* or the IdP's discovery document (no authorization or token endpoint, or
* PKCE required and `S256` not offered).
*/
export declare class OidcSignInSetupError extends Error {
readonly code: "ERR_OIDC_SIGN_IN_SETUP";
readonly setting: 'client-key' | 'discovery';
constructor(setting: 'client-key' | 'discovery', sentence: string);
}
export declare function oidcSignIn(options: OidcSignInOptions): RedirectSignIn;