Files
curo1305andClaude Sonnet 4.6 b8e0e3adec test(07.2): complete automated UAT — 7/7 pass
All Phase 7.2 behaviors verified end-to-end against the running app:
- JTI UUID claim present in every issued access token
- Token rejected (Session invalidated) after password change
- Refresh cookie survives password change (skip_token_hash)
- Token rejected after enable-TOTP and disable-TOTP
- Token rejected after admin deactivation
- Reactivation does NOT write user_nbf (no spurious revocation)

Findings recorded in UAT.md:
- Workers must be restarted after Phase 7.2 deploy (--workers 2 does not hot-reload)
- D-02 same-second edge case confirmed benign in real usage
- Deactivation fires is_active check before user_nbf in same-second scenarios (belt-and-suspenders)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 11:47:59 +02:00

3.1 KiB

status, phase, source, started, updated
status phase source started updated
complete 07.2-security-jti-claim-redis-access-token-revocation-inserted 07.2-01-SUMMARY.md, 07.2-02-SUMMARY.md, 07.2-03-SUMMARY.md 2026-06-06T09:40:00Z 2026-06-06T11:50:00Z

Current Test

[testing complete]

Tests

1. JTI claim present and is a valid UUID

expected: Decoded JWT payload contains a "jti" key with a valid UUID string (e.g. "522fe72f-c86d-43bd-8a8f-ae47f577d37d"). result: pass

2. Old token rejected after password change

expected: Token issued before a password change returns HTTP 401 "Session invalidated" on the next request. result: pass

expected: The refresh cookie (kept alive via skip_token_hash) can be exchanged for a fresh access token that passes authentication. result: pass

4. Old token rejected after enabling TOTP

expected: Token issued before TOTP was enabled returns HTTP 401 "Session invalidated". result: pass

5. Old token rejected after disabling TOTP

expected: Token issued before TOTP was disabled returns HTTP 401 "Session invalidated". result: pass

6. Token rejected after admin deactivation

expected: Token issued before admin deactivation returns HTTP 401. Message may be "Session invalidated" (user_nbf fired) or "User not found or deactivated" (is_active check fired — same-second D-02 edge case). Both are correct. result: pass

7. Admin reactivation does NOT cause spurious token revocation

expected: A token issued after reactivation works normally. Reactivation must not write user_nbf. result: pass

Summary

total: 7 passed: 7 issues: 0 pending: 0 skipped: 0 blocked: 0

Gaps

[none]

Findings

Critical: Backend workers were stale (required restart before testing)

The backend runs with --workers 2 (not --reload). Workers forked 27 hours ago, before Phase 7.2 code was committed. The code files on disk were correct (volume-mounted), but the running processes held the pre-Phase-7.2 module in memory:

  • JTI was missing from all issued tokens
  • user_nbf Redis check was absent from get_current_user

Resolution: docker compose restart backend loaded the current code. All 7 tests then pass.

Risk this surfaces: Any environment where the backend is not restarted after deploying Phase 7.2 will have zero JTI coverage and zero NBF revocation. This is a deployment gap, not a code bug.

Noted: D-02 same-second edge case (by design)

Tests 2 and 4 require a 1-second sleep between login and the security event to guarantee iat < user_nbf. This is the documented edge case in D-02: "a token issued exactly at the event second is allowed." This is an acceptable trade-off — in real usage, tokens are issued minutes before security events.

Noted: Test 6 rejection message

After admin deactivation, the 401 response body is "User not found or deactivated" rather than "Session invalidated". This is because is_active=False is checked first in get_current_user. The user_nbf Redis key is also written by deactivation, but in same-second scenarios the is_active check fires first. Both mechanisms correctly block the token — this is belt-and-suspenders.