Repository navigation
auth: centralize token revocation checks and resolve rate-limit client addresses - #750
Conversation
Bearer verification now goes through one revocation-list read shared by get_current_user, the issuer's session reads at /authorize, token exchange and the service-token boundaries. Session access tokens carry the session's rotation family so session-level revocation reaches them. Sign-out and session revocation endpoints get dedicated dependencies so they keep working while Redis is unavailable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All slowapi limiters now use one key function that resolves the client address through TRUSTED_PROXIES, the same resolution the sign-in link limits already use (IPv6 per /64). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rate-limit keys now resolve the client address through TRUSTED_PROXIES. Trust the pod network so the tunnel's forwarded client address is used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📚 Documentation checks found issues. Please review the maintenance script output. |
|
|
Security Scan SummaryDate: Tue Oct 27 23:12:40 UTC 2026 Scan Results
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📚 Documentation checks found issues. Please review the maintenance script output. |
🎭 Playwright E2E Test Results
|
|
|
Security Scan SummaryDate: Tue Oct 27 23:17:24 UTC 2026 Scan Results
|
🎭 Playwright E2E Test Results
|
|
📚 Documentation checks found issues. Please review the maintenance script output. |
|
|
Security Scan SummaryDate: Wed Oct 28 00:18:59 UTC 2026 Scan Results
|
🎭 Playwright E2E Test Results
|
…on fixture override is_revoked called strict_exists on a missing client, which answered 500. A missing or non-strict client now raises RedisUnavailableError, so strict paths answer 503 like any outage. The invitation Postgres fixture also overrides the get_redis that app.dependencies declares (tests/conftest.py swaps the module attribute after it was imported). 25/25 pass locally against a synthetic PostgreSQL + Redis. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📚 Documentation checks found issues. Please review the maintenance script output. |
|
|
Security Scan SummaryDate: Wed Oct 28 04:16:17 UTC 2026 Scan Results
|
🎭 Playwright E2E Test Results
|
…akeRedis in tests verify_unrevoked_token received the raw FakeRedis that tests/conftest.py hands out, which has no strict read, and that single instance was bound to the first test's event loop (later tests: 'bound to a different event loop' -> 500). is_revoked now wraps a raw client in ResilientRedisClient (still fails closed on no client), and get_fake_redis returns one instance per running loop. Full unit suite: the two mail-boundary failures are gone; remaining local failures are environment-only (xmlsec, defusedxml, old cryptography) and identical without this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📚 Documentation checks found issues. Please review the maintenance script output. |
|
|
… set CI lints only changed files. Import-order and dict-comprehension fixes (ruff --fix) and removal of the first mock_redis fixture, which the later definition already shadowed at import (no behaviour change). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📚 Documentation checks found issues. Please review the maintenance script output. |
Security Scan SummaryDate: Wed Oct 28 05:54:00 UTC 2026 Scan Results
|
|
|
| if _fake_redis_instance is None: | ||
| _fake_redis_instance = fakeredis.aioredis.FakeRedis(decode_responses=True) | ||
| return _fake_redis_instance | ||
| import asyncio |
Security Scan SummaryDate: Wed Oct 28 05:56:47 UTC 2026 Scan Results
|
🎭 Playwright E2E Test Results
|
🎭 Playwright E2E Test Results
|
Strict token-revocation reads need a reachable Redis. The invitation proofs connect to 127.0.0.1:6379 in CI; without a service every bearer request in them failed with ConnectionError -> 500. Mirrors the api-tests job's Redis service. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📚 Documentation checks found issues. Please review the maintenance script output. |
|
|
Security Scan SummaryDate: Wed Oct 28 09:46:01 UTC 2026 Scan Results
|
🎭 Playwright E2E Test Results
|
Summary
get_current_userand its optional/GraphQL variants,/authorize, token exchange, and the service boundaries) now shares one revocation check: a single RedisEXISTSover the token's jti and session-family keys. Session access tokens carry the session family, so revoking a session also applies to tokens issued before a refresh.Retry-After). Sign-out is exempt.TRUSTED_PROXIES, the same resolver the sign-in link limits already use, instead of the socket peer.TRUSTED_PROXIESadds the pod network (10.42.0.0/16) to the localhost defaults. The NetworkPolicy admits only tunnel and application pods to the API port.Tests
test_access_token_revocation.py: 16 tests.main.Follow-ups
X-Forwarded-Forwithout the trusted-proxy check.🤖 Generated with Claude Code