Summary#
- Implements
POST /xrpc/com.atproto.server.refreshSessionper the ATProto spec - Token rotation: old refresh token is invalidated (marked via
next_jti) and a new access + refresh pair is issued atomically - Replay detection: presenting an already-rotated refresh token triggers full session revocation (session + all its refresh tokens deleted)
- Refactors
issue_access_jwt/issue_refresh_jwtfromcreate_session.rsintoauth/jwt.rsso both routes share them without cross-route imports - Promotes
extract_bearer_tokentopub(crate)for direct use in route handlers
Test plan#
-
valid_refresh_token_returns_new_token_pair— 200 with accessJwt, refreshJwt, did, handle -
new_access_jwt_has_access_scope— new access JWT has correct scope claim -
new_refresh_jwt_has_refresh_scope_and_different_jti— new refresh JWT has fresh jti -
token_rotation_stored_in_db— old token's next_jti set, new token in DB -
old_refresh_token_rejected_after_rotation— reusing rotated token returns error -
replay_of_used_refresh_token_revokes_session— session and all tokens deleted on replay -
expired_refresh_token_returns_error— expired JWT rejected before DB hit -
invalid_token_signature_returns_error— tampered/garbage token rejected -
access_token_rejected_as_refresh_token— scope mismatch returns error -
missing_authorization_header_returns_error— no Bearer header returns error