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 aBearertoken in theAuthorizationheader and, on success, exposes the token claims to downstream nodes viacontext.message. Validation is either local JWT verification against the provider’s JWKS (bykid, cached with a TTL, refetched once on an unknownkid) 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 toredirect_uriwith a code; the plugin exchanges it for tokens, validates theid_token, and seals the resulting claims into an encrypted client-side session cookie (seecrate::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 sharessession.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.lifetimeexpiry 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’srefresh_token/expires_inalongside the session; a read that finds the access token within 30s ofexpires_attransparently 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. Setsession.refresh: falseto disable (defaulttrue). 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§
- Cached
Jwks 🔒 - Cached JWKS with the time it was fetched, for TTL-based expiry.
- Flow
State 🔒 - Transient state carried in the short-lived flow cookie across the redirect
to the IdP and back to the callback (CSRF
state, replaynonce, PKCEverifier, 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": [ ... ] }). - Openid
Connect Plugin - Authenticates requests by validating a bearer access token via JWKS signature verification or token introspection.
- Session
Data 🔒 - The sealed session payload: the validated identity, kept small.
Enums§
- Refresh
Failure 🔒 - 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.Storeis a genuine session-store failure and maps toOpenidConnectPlugin::store_error(503) same as everywhere else. - Token
Error 🔒 - 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).Infraexits through the node’serrorport — the node could not do its job;Deniedexits throughdenied— the node did its job and the token was rejected.
Functions§
- alg_
matches_ 🔒kty - Whether
algcan be verified with a key of JWK typekty. - algs_
for_ 🔒key - Narrows the configured algorithms to those a
ktykey can verify. - audience_
contains 🔒 - True when
audequalsclient_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 toallowed_algs) andexp, returning the decoded claims. Issuer/audience are validated separately byOpenidConnectPlugin::validate_claims. - first_
query 🔒 - First value of a query parameter.
- form_
encode 🔒 - Percent-encodes a token for an
application/x-www-form-urlencodedbody. - jwk_
to_ 🔒decoding_ key - Builds a [
DecodingKey] from a JWK based on its key type. - now_
unix 🔒 - Current time, epoch seconds. Used for
expires_atbookkeeping 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
Authorizationheader 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
redirectport (wire the node’sredirectedge toclient.in). - request_
is_ 🔒https - True when the request arrived over HTTPS (controls the cookie
Secureflag). - 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 nokidis present. - session_
cookie_ 🔒field - Reads a session cookie string field from nested
session.cookie.<field>, falling back to the flatsession_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 flatsession_refreshkey the Web UI schema would emit; defaulttrue. 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/.