Askr documentation
Server & APIs

OIDC

OIDC at the Askr server boundary, with validated input and explicit failure states.

Example

Use discovery and authorization-code flow helpers at the server boundary; validate state, nonce, redirect URI, and issuer on callback.

import { createOidcClient } from '@askrjs/auth/oidc';

const oidc = await createOidcClient({
  issuer: env.OIDC_ISSUER,
  clientId: env.OIDC_CLIENT_ID,
  redirectUri: env.OIDC_REDIRECT_URI,
});

Discovery

createOidcClient(options: OidcClientOptions) takes issuer, clientId, an optional clientSecret, redirectUri, scopes, and an injectable fetch, and returns an OidcClient. Its discover() method fetches the provider's OidcProviderMetadata - authorization_endpoint, token_endpoint, jwks_uri, and the optional userinfo_endpoint and end_session_endpoint - so you don't hardcode those URLs per provider.

Authorization flow

createAuthorizationRequest(options?: {state?, nonce?, codeVerifier?, loginHint?}) builds the redirect URL for the provider's authorization endpoint and returns it alongside the state, nonce, and PKCE codeVerifier it used - generating any of the three for you if you don't supply them. The caller's only job is to persist those values (typically in a short-lived cookie) so they're available when the browser comes back to the callback route.

Callback validation

Once the browser returns with a code, exchangeCode({code, state, request: {state, nonce, codeVerifier}}) posts to the provider's token endpoint and resolves to { tokens, principal } - it already validates the ID token internally (signature, issuer, audience, and the nonce you stored earlier) as part of the exchange, rejecting with an OidcClientError('invalid-id-token', ...) if any of those checks fail. There's no separate validateOidcIdToken() call to make on this path; that function exists for validating an ID token you obtained some other way, not as a required second step after exchangeCode().

Session establishment

Neither createOidcClient nor validateOidcIdToken create an application session - that's left to you deliberately, since how you store sessions is covered under Model and Sessions. After the code exchange and ID token check succeed, a callback handler typically creates a SessionStore entry or issues your own JWT via createJwtIssuer, then sets a cookie with @askrjs/server's ctx.setCookie(), the same way the framework's built-in auth routes do.