nic-6443 commented on PR #13792: URL: https://github.com/apache/apisix/pull/13792#issuecomment-5215562406
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. | Project | Session storage | Per-request introspection of session token | Back-channel logout | Actual revocation mechanism | |---|---|---|---|---| | mod_auth_openidc | server-cache (default) / cookie | No — introspection lives entirely under `OIDCOAuth*`, the RS path | Yes, with `jti` replay cache | back-channel logout + `OIDCRefreshAccessTokenBeforeExpiry` | | Traefik Hub | cookie / Redis | No | Yes (`backchannelLogoutUrl`) | back-channel logout | | traefikoidc (community plugin) | cookie / Redis | No — introspection is bearer-only by design | Yes (`enableBackchannelLogout`) | back-channel logout, Redis required for multi-replica | | Spring Security | HttpSession | No | Yes, since 6.2 (`OidcBackChannelLogoutHandler` in 6.4) | back-channel logout | | Kong OIDC | cookie / Redis / memcache | No — `reverify` is local JWT verification only | No | server-side session + revoke on logout | | oauth2-proxy | cookie / Redis | No | No, requested since 2021 | `--cookie-refresh` periodic refresh grant | | Envoy OAuth2 filter | HMAC cookie | No | No, open issue | RP-initiated logout only | | NGINX Plus nginx-openid-connect | keyval (server-side) | No | No | keyval + `/logout` deletes the key | | Pomerium | databroker (fully server-side) | No | No | log out when refresh fails + admin revocation | | Gloo Gateway | cookie / Redis | No — `introspectionUrl` applies to header tokens | No | Redis session + `logoutPath` | | Ory Oathkeeper | none | Yes, per request by default | N/A | introspection | Oathkeeper is the only per-request introspector, and it has no session concept at all — it handles pure bearer traffic, which is the path `introspect()` already covers here. The mod_auth_openidc row is probably the most relevant one, being the same author as lua-resty-openidc and a much older codebase. Every introspection directive there is namespaced `OIDCOAuth*`, i.e. the OAuth 2.0 Resource Server path, and the session path has no introspection option at all. What it offers for the session path instead is `OIDCRefreshAccessTokenBeforeExpiry <seconds> [logout_on_error | authenticate_on_error | 502_on_error]`: refresh the token ahead of expiry and treat a failed refresh, meaning the OP revoked the refresh token, as a logout. `--cookie-refresh` in oauth2-proxy and Pomerium's "log out when refresh fails" are the same idea. That's a third option neither this PR nor #13750 mentions, and it's the most widely adopted one in the survey — it needs no introspection support from the OP, and the detection delay is bounded by the refresh interval instead of costing an IdP round trip per request. One correction to the PR description while I'm here: back-channel logout may be closer than "out of scope" suggests. `session.storage = "redis"` landed in #12986, so the server-side storage prerequisite already exists. What's missing is narrower — a `sid` to session-key reverse index written at login from the ID token's `sid` claim, plus the logout endpoint and logout token validation. lua-resty-openidc has no back-channel logout support, so that part would have to live in the plugin. Separately, the cache key here including the endpoint, `client_id` and `cache_segment` is worth keeping regardless of direction. Oathkeeper shipped a CVE (GHSA-qvp4-rpmr-xwrr) precisely because its introspection cache didn't distinguish introspection URLs, so a token primed against one server could be replayed against rules pointing at another. The one thing I'd reconsider is the default. `introspection_interval = 0` means an IdP round trip on every request, while every comparable mechanism above operates on a minutes timescale. Framing this as bounded-delay periodic revalidation rather than per-request real-time verification would make the cost a lot easier to justify. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
