fix(auth): close same-ms revocation race + tidy audit cleanup

Bumps token_revoked_before by 1ms so a JWT issued in the same millisecond
as a logout call (Date.from(Instant.now()) quantises iat to ms) does not
survive the filter's strict isBefore check.

Also extends LogoutControllerIT @AfterEach to delete the audit_log row,
keeping reused Postgres containers clean for downstream ITs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-27 09:26:05 +02:00
parent 9031533077
commit 83a10de497
2 changed files with 6 additions and 1 deletions

View File

@@ -192,7 +192,11 @@ public class UiAuthController {
return ResponseEntity.noContent().build();
}
String userId = stripSubjectPrefix(authentication.getName());
userRepository.revokeTokensBefore(userId, Instant.now());
// +1ms guards against same-millisecond races: JWT iat is quantised to
// milliseconds (Date.from(now) in JwtServiceImpl), and the filter check
// is strict isBefore. Without the bump, a token issued in the same
// millisecond as logout would survive revocation.
userRepository.revokeTokensBefore(userId, Instant.now().plusMillis(1));
auditService.log(userId, "logout", AuditCategory.AUTH, null, null,
AuditResult.SUCCESS, httpRequest);
log.info("UI user logged out: {}", userId);

View File

@@ -30,6 +30,7 @@ class LogoutControllerIT extends AbstractPostgresIT {
@AfterEach
void cleanup() {
userRepository.delete("logout-test");
jdbc.update("DELETE FROM audit_log WHERE username = ?", "logout-test");
}
@Test