Java 11, Spring Security here. I have the following endpoint/method in my @RestController
:
@GetMapping("/centerPoint") public void centerPoint(@AuthenticationPrincipal ExpiringUsernameAuthenticationToken token, HttpServletResponse response) throws IOException { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth == null) { LOGGER.warn("Current authentication instance from security context is null"); response.sendRedirect("some redirect url"); return; } SAMLCredential attributes = ((SAMLCredential) token.getCredentials()); // ...rest of code omitted for brevity }
When I set a breakpoint inside this method and login to my app, token
is null
(meaning it was not properly injected as an @AuthenticatedPrincipal
) however SecurityContextHolder.getContext().getAuthentication()
returns an Authentication
instance that looks totally fine. I get a NPE when the token.getCredentials()
gets called at the bottom there.
I know this is an incomplete code snippet and I’m happy to provide other parts of the security code (WebSecurityConfig
, etc.) however I’m wonder: what would cause SecurityContextHolder.getContext().getAuthentication()
to be non-null, but not have a token
to inject?
Advertisement
Answer
The javadoc in AuthenticationPrincipalArgumentResolver
says the following:
Will resolve the CustomUser argument using Authentication.getPrincipal() from the SecurityContextHolder. If the Authentication or Authentication.getPrincipal() is null, it will return null. If the types do not match, null will be returned unless AuthenticationPrincipal.errorOnInvalidType() is true in which case a ClassCastException will be thrown.
So you should make sure that the Authentication.getPrincipal()
type is ExpiringUsernameAuthenticationToken
.
Debug your application and see which type returns from SecurityContextHolder.getContext().getAuthentication()
and from authentication.getPrincipal()