Skip to main content

Module openid_connect

Module openid_connect 

Source
Expand description

OpenID Connect authentication plugin (openid-connect).

Two modes, selected by bearer_only:

  • Resource-server / bearer mode (bearer_only: true, the default): validates an OAuth2 / OIDC access token presented as a Bearer token in the Authorization header and, on success, exposes the token claims to downstream nodes via context.message. Validation is either local JWT verification against the provider’s JWKS (by kid, cached with a TTL, refetched once on an unknown kid) or RFC 7662 token introspection.

  • Interactive login (bearer_only: false): the full Authorization Code flow with PKCE. An unauthenticated browser is redirected to the identity provider; the provider redirects back to redirect_uri with a code; the plugin exchanges it for tokens, validates the id_token, and seals the resulting claims into an encrypted client-side session cookie (see crate::plugins::util::cookie_session). Subsequent requests carrying a valid session cookie are let through with the claims attached. No server-side session store is needed, so this works across a horizontally-scaled deployment as long as every instance shares session.secret.

§Flow wiring (interactive mode)

In interactive mode the node exits through the dedicated redirect port whenever the browser must move (the 302 to the IdP, the post-callback 302 back to the original URL, or a logout redirect) — wire redirect to client.in. Deliberate rejections (missing/invalid flow cookie, CSRF state mismatch, an invalid id_token, or a nonce mismatch) exit through denied — wire it to client.in too, or a custom denial handler. Genuine provider failures (discovery, JWKS, or token-endpoint callouts that transport-fail, return a non-2xx status, or hand back unparseable data) exit through the ordinary error port, since the node could not do its job. Only a request that arrives with a valid session cookie continues out success toward the upstream. The node must be on a route whose match rule also covers the redirect_uri path so the callback reaches it.

§Deviations from APISIX

  • No server-side session revocation. Sessions live entirely in the encrypted cookie, so a session cannot be invalidated before its session.cookie.lifetime expiry without a shared denylist (a future feature). Use short lifetimes. This is the standard client-side-cookie trade-off APISIX shares when configured for cookie sessions.
  • Token refresh, redis mode only. When session.storage: redis, the callback captures the token response’s refresh_token/expires_in alongside the session; a read that finds the access token within 30s of expires_at transparently refreshes it at the token endpoint before attaching identity, coordinated across concurrent requests via the store’s short-lived lock (SessionStore::try_lock/unlock) so only one request per session performs the callout — losers re-read the (usually already-refreshed) session instead of also calling the IdP. An id_token in the refresh response is re-validated and its claims replace the session’s; an IdP-side refresh failure (unreachable, non-2xx, invalid id_token) is not a store outage, so it falls back to a fresh login rather than a 503. Set session.refresh: false to disable (default true). Cookie-mode sessions have no server-side coordination point for this, so they keep the original behavior: when the session cookie expires the user re-authenticates (a fresh, fast redirect round-trip if the IdP session is still valid).
  • Only the Authorization Code grant is implemented (the OIDC gateway case); implicit/hybrid flows are not.

Structs§

CachedJwks 🔒
Cached JWKS with the time it was fetched, for TTL-based expiry.
FlowState 🔒
Transient state carried in the short-lived flow cookie across the redirect to the IdP and back to the callback (CSRF state, replay nonce, PKCE verifier, and where to send the browser after login).
Interactive 🔒
Interactive-mode configuration, present only when bearer_only: false.
Jwk 🔒
A single JSON Web Key from a provider’s JWKS document.
JwkSet 🔒
A JWKS document ({ "keys": [ ... ] }).
OpenidConnectPlugin
Authenticates requests by validating a bearer access token via JWKS signature verification or token introspection.
SessionData 🔒
The sealed session payload: the validated identity, kept small.

Enums§

RefreshFailure 🔒
Outcome of a redis-mode refresh attempt (OpenidConnectPlugin::do_refresh). ReAuth (IdP unreachable/errored, or the refreshed id_token failing validation) is not a store outage — the caller falls back to re-login, never a 503. Store is a genuine session-store failure and maps to OpenidConnectPlugin::store_error (503) same as everywhere else.
TokenError 🔒
Distinguishes a genuine provider/infrastructure failure (discovery, JWKS, or introspection endpoint unreachable, non-2xx, or unparseable) from the presented token being deliberately invalid (bad signature, unknown kid, wrong issuer/audience, expired, or inactive). Infra exits through the node’s error port — the node could not do its job; Denied exits through denied — the node did its job and the token was rejected.

Functions§

alg_matches_kty 🔒
Whether alg can be verified with a key of JWK type kty.
algs_for_key 🔒
Narrows the configured algorithms to those a kty key can verify.
audience_contains 🔒
True when aud equals client_id (string aud) or contains it (array aud).
build_interactive 🔒
Builds the interactive-mode configuration from the plugin config.
decode_and_validate 🔒
Verifies the token signature (against key, restricted to allowed_algs) and exp, returning the decoded claims. Issuer/audience are validated separately by OpenidConnectPlugin::validate_claims.
first_query 🔒
First value of a query parameter.
form_encode 🔒
Percent-encodes a token for an application/x-www-form-urlencoded body.
jwk_to_decoding_key 🔒
Builds a [DecodingKey] from a JWK based on its key type.
now_unix 🔒
Current time, epoch seconds. Used for expires_at bookkeeping on the redis-mode refresh path.
parse_alg 🔒
Parses one algorithm name into a [jsonwebtoken::Algorithm] (asymmetric only — OIDC JWKS keys are RSA/EC).
parse_allowed_algs 🔒
Parses token_signing_alg_values_expected (string, comma/space list, or array) into the allowed-algorithm set, defaulting to the common asymmetric algorithms.
parse_bearer 🔒
Extracts the bearer token from an Authorization header value.
parse_introspection 🔒
Parses an RFC 7662 introspection response, requiring active: true. An unparseable response is a genuine provider failure (TokenError::Infra); an inactive token is a deliberate rejection (TokenError::Denied).
pkce_challenge 🔒
PKCE S256 challenge: base64url(SHA-256(verifier)).
random_token 🔒
A URL-safe random token (32 bytes → base64url) for state/nonce/PKCE.
read_audience_cfg 🔒
Reads claim_validator.audience.{claim,required,match_with_client_id}.
read_valid_issuers 🔒
Reads claim_validator.issuer.valid_issuers.
redirect 🔒
Prepares a 302 redirect on the context and exits through the dedicated redirect port (wire the node’s redirect edge to client.in).
request_is_https 🔒
True when the request arrived over HTTPS (controls the cookie Secure flag).
request_uri 🔒
Rebuilds the request URI (path plus sorted query string) for the post-login redirect target.
select_jwk 🔒
Selects the JWK matching kid, or the sole key when no kid is present.
session_cookie_field 🔒
Reads a session cookie string field from nested session.cookie.<field>, falling back to the flat session_cookie_<field> form the Web UI schema emits (the SchemaForm is flat and cannot author nested maps).
session_field 🔒
Reads session.<field> as a string.
session_refresh_enabled 🔒
Reads session.refresh (nested), falling back to the flat session_refresh key the Web UI schema would emit; default true. Redis-mode only — cookie mode never attempts a refresh regardless.
string_opt 🔒
Reads an optional non-empty string config value.
url_path 🔒
Extracts the path portion of a URL (everything from the first / after the authority), defaulting to /.