Skip to content

feat(auth): harden authentication against token replay#1100

Open
SanidhyaDhangar wants to merge 1 commit into
imDarshanGK:mainfrom
SanidhyaDhangar:feat/490-harden-token-replay
Open

feat(auth): harden authentication against token replay#1100
SanidhyaDhangar wants to merge 1 commit into
imDarshanGK:mainfrom
SanidhyaDhangar:feat/490-harden-token-replay

Conversation

@SanidhyaDhangar

Copy link
Copy Markdown

Summary

Closes #490.

A valid access token that gets captured can currently be replayed until it expires, and there's no way to invalidate one early (e.g. on logout). This PR adds a way to revoke individual tokens and rejects revoked ones.

What changed

  • Every access token now carries a unique jti (token id) and an iat (issued-at) claim.
  • New token_denylist module: a TTL-bounded, thread-safe in-memory store of revoked jtis. Entries are only kept until the token's own exp, then purged, so memory stays bounded. The interface is small on purpose so it can be backed by Redis later (the project already exposes settings.redis_url) without touching call sites.
  • New POST /auth/logout endpoint that revokes the caller's current token.
  • get_current_user now rejects any revoked token with 401.

Behaviour

  • Replaying a token after logout → 401 Token has been revoked.
  • Other active sessions/tokens for the same user keep working.
  • Tokens issued before this change (no jti) are handled gracefully.

Tests

Added to backend/tests/test_auth_endpoints.py (8 passing):

  • logout then reuse the same token → 401
  • a second token stays valid after the first is revoked
  • issued tokens carry a unique jti / iat

Checklist

  • My PR title follows the format: feat/fix/docs/test: short description
  • I have added tests for new features
  • No hardcoded secrets or API keys in my code
  • This PR is linked to a GSSoC 2026 issue
  • I have updated docs/CHANGELOG.md

Access tokens now carry a unique `jti` (and `iat`). A server-side
revocation denylist lets a token be invalidated before its `exp`, so a
captured-but-revoked token can no longer be replayed.

- Add `token_denylist`: a TTL-bounded, thread-safe, in-memory revocation
  store with a Redis-swappable interface.
- Add `POST /auth/logout` to revoke the caller's current token.
- Reject revoked tokens in `get_current_user` with 401.
- Tests: replaying a token after logout returns 401; other sessions
  stay valid; tokens carry a unique jti/iat.

Closes imDarshanGK#490
@SanidhyaDhangar

Copy link
Copy Markdown
Author

Implemented token-replay hardening as discussed: unique jti per token + a server-side denylist, a POST /auth/logout to revoke tokens, and 401 on replay. Tests included and passing. Ready for review — happy to adjust anything

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden authentication endpoints against token replay

1 participant