ARTICLE AD BOX
TLDR
if you are setting any instance of AbstractAuthenticationToken in your securityContext - it has to include an authority with issuedAt time:
new UsernamePasswordAuthenticationToken("some name", "some credentials", List.of( FactorGrantedAuthority.withAuthority("Some Authority") .issuedAt(Instant.now()) .build() ));Explanation
The issue is due to the Spring Boot 4.0.6 also updating spring-boot-starter-oauth2-authorization-server's version to 7.0.5.
In version 7.0.5, JwtGenerator class is no longer taking the authenticationTime from request, as it used to in 7.0.4:
claimsBuilder.claim(IdTokenClaimNames.AUTH_TIME, sessionInformation.getLastRequest());but instead now uses following logic:
claimsBuilder.claim(IdTokenClaimNames.AUTH_TIME, getAuthenticationTime(context.getPrincipal())); //... static Date getAuthenticationTime(Authentication authentication) { Instant authenticationTime = null; for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) { if (grantedAuthority instanceof FactorGrantedAuthority factorGrantedAuthority) { if (authenticationTime == null || factorGrantedAuthority.getIssuedAt().isAfter(authenticationTime)) { authenticationTime = factorGrantedAuthority.getIssuedAt(); } } } Assert.notNull(authenticationTime, "authenticationTime cannot be null"); return Date.from(authenticationTime); }So it is now trying to read the authenticationTime from list of authorities, which doesn't work if somewhere along the line, anyone is setting authentication object manually (due to whatever custom logic).
So in short, something like this no longer works:
new UsernamePasswordAuthenticationToken("some name", "some credentials", List.of());it now, has to include the issuedAt, e.g.:
new UsernamePasswordAuthenticationToken("some name", "some credentials", List.of( FactorGrantedAuthority.withAuthority("Some Authority") .issuedAt(Instant.now()) .build() ));