feat(openid-connect): introspect the session-held access token - #13792
feat(openid-connect): introspect the session-held access token#13792janiussyafiq wants to merge 2 commits into
Conversation
The authorization code flow stores tokens in the session cookie and nothing revisits the identity provider until the stored expiry passes, so a token revoked at the provider keeps being forwarded upstream. Add an opt-in introspect_session_access_token option: an inactive verdict destroys the session and follows unauth_action (negative verdicts cached 10s against cookie replays), a transport failure returns 503 while keeping the session, and active verdicts are cached only when introspection_interval > 0. Fixes apache#13750
…-introspection # Conflicts: # t/plugin/openid-connect.t
|
I went looking at how other OIDC-capable gateways and proxies handle revocation of a session-held token, since it seemed worth knowing what the prior art looks like. Sharing the survey — the short version is that none of the browser-session implementations introspect the session token per request. They either wait for a back-channel logout notification, or re-validate periodically through the refresh grant.
Two notes on reading the table. Oathkeeper is the only per-request introspector, and it has no session concept at all — it handles pure bearer traffic, which is the path And the refresh-based mechanism in the last column: mod_auth_openidc exposes it as The mod_auth_openidc row may be the most directly comparable, being the same author as lua-resty-openidc: every introspection directive there is namespaced |
Description
In the authorization code flow the tokens live in the session cookie, and nothing revisits the identity provider until the stored token expiry passes: a token revoked at the provider (logout via another application, administrative session termination) keeps being accepted and forwarded upstream until it expires.
This adds an opt-in
introspect_session_access_tokenoption that introspects (RFC 7662) the access token held in the session on every request:unauth_action. The negative verdict is cached for 10 seconds so replays of a discarded session cookie do not flood the introspection endpoint. The TTL is deliberately a fixed constant rather than a schema field: it has no user-facing semantic to tune, and reusingintrospection_intervalwould both disable the protection at its default0and conflate it with how long a positive verdict may be trusted. It can be promoted to a schema field later if a need appears.503and keeps the session — deliberately fail-closed, also underunauth_action=pass, so a possibly revoked token never reaches the upstream while a provider hiccup does not log the whole user base out.introspection_interval > 0; the default introspects every request, since a cached "active" delays revocation detection by its TTL.Not allowed together with
bearer_only(rejected by the schema): header-presented tokens are already introspected; only the session path lacked revocation checking. lua-resty-openidc deliberately leaves this to the caller (see zmartzone/lua-resty-openidc#412) and exposes the pieces used here (call_token_endpoint,get_discovery_doc). OIDC Back-Channel Logout would be the complementary mechanism, but it requires server-side session storage indexed bysid, so it is out of scope here.Which issue(s) this PR fixes:
Fixes #13750
Checklist