fix(proxy): revoke all cached tokens during backchannel logout - #3477
fix(proxy): revoke all cached tokens during backchannel logout#3477zerox80 wants to merge 7 commits into
Conversation
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Security | 1 critical |
🟢 Metrics 283 complexity
Metric Results Complexity 283
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Add token-specific session keys and separate revocation keys. Keep the legacy subject/session key format readable while allowing multiple tokens to belong to one session. Match both subject and session when both are supplied and avoid truncating logout lookups after 1,000 cache entries. Include unit tests for key compatibility, multiple tokens, and subject isolation. Authentication starts using these records in the logout fix.
Store absolute record expiry with the value so Redis and NATS retain the same lifetime information as memory stores. Use a dedicated OIDC namespace without a bucket-wide TTL, migrate legacy cached tokens before startup, and clean up expired records with the proxy context. Keep logout state when claims caching is disabled. Add expiry, migration, cleanup, and memory/Redis/NATS backend tests alongside the cache changes.
Register tokens synchronously before caching claims and check revocation before authentication and after registration. Revoke every token matching the logout subject or session independently of its cached claims, preserving the original token expiry. Notification failures must not skip invalidation. Add HTTP regressions for refreshes and userinfo bypass, concurrent claims writes, disabled claims caching, missing expiry, and storage failures.
Document the dedicated OIDC namespace, legacy cache migration, shared-store requirements, expiry cleanup, and retention for tokens without verified expiry. Add the changelog entry for the complete backchannel logout fix.
32eaef5 to
6c4da8b
Compare
|
Could you mark this finding as a false positive and rerun Codacy? It occurs in an integration test: the executable name is fixed to redis-server, arguments are passed without a shell, and the socket path comes from t.TempDir(). No untrusted request input reaches this call. |
|
This means you're logged out from every session on every browser/device, right? |
the scope depends on the logout token. When it contains a sid, only the tracked tokens belonging to that session are revoked; other sessions of the same user remain authenticated. When it contains only sub, all tracked sessions for that user are targeted, as specified by oidc back-channel logout. |
|
Thanks for the clarification! |
Description
When a session receives a refreshed access token, its cache lookup currently replaces the previous token's hash. Backchannel logout can therefore leave older cached tokens usable. Deleting cached claims also allows a locally verified JWT to authenticate again when
PROXY_OIDC_SKIP_USER_INFOis enabled.Register each accepted token separately and retain revocations independently of cached claims. Logout invalidates every tracked token matching the requested subject or session. Authentication checks revocation before using a token and after registering new claims, so a concurrent claims write cannot restore a logged-out token. Notification failures no longer prevent invalidation.
Preserve per-record expiry across memory, Redis, and NATS using a dedicated OIDC cache namespace. Import unexpired legacy claims on startup and clean up expired records. Empty legacy NATS buckets require no migration. Physically purge NATS delete markers within the configured table and through the observed revision, preserving concurrent writes. This prevents a bucket-wide TTL from dropping revocations before their tokens expire while keeping expired state from accumulating.
Commit sequence
Tests are included with the behavior they validate. The first four commits split the original patch; the final two address the NATS startup and cleanup review findings.
Related Issue
No issue linked.
Motivation and Context
Backchannel logout must invalidate all tokens already accepted for the affected session, including tokens issued before a refresh and tokens verified without a userinfo request.
Revocations are retained until the verified token expiry. Tokens without a verified expiry, including migrated legacy entries, retain logout state indefinitely. All proxy instances must use the updated code and the same persistent store to share revocations; memory-backed state is lost on restart. The proxy documentation explains the cache namespace and upgrade behavior.
How Has This Been Tested?
Test environment: Ubuntu under WSL, Go 1.25.9, vendored dependencies, Redis 7.0.15, and the vendored NATS server.
Types of changes
Checklist