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:
@@ -192,7 +192,11 @@ public class UiAuthController {
|
|||||||
return ResponseEntity.noContent().build();
|
return ResponseEntity.noContent().build();
|
||||||
}
|
}
|
||||||
String userId = stripSubjectPrefix(authentication.getName());
|
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,
|
auditService.log(userId, "logout", AuditCategory.AUTH, null, null,
|
||||||
AuditResult.SUCCESS, httpRequest);
|
AuditResult.SUCCESS, httpRequest);
|
||||||
log.info("UI user logged out: {}", userId);
|
log.info("UI user logged out: {}", userId);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class LogoutControllerIT extends AbstractPostgresIT {
|
|||||||
@AfterEach
|
@AfterEach
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
userRepository.delete("logout-test");
|
userRepository.delete("logout-test");
|
||||||
|
jdbc.update("DELETE FROM audit_log WHERE username = ?", "logout-test");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user