Spring Controller argument `@AuthenticationPrincipal Jwt principal` causes Exception: tokenValue can not be empty

Viewed 454

The controller method looks like this

QuotaChangeResponseDTO memoryQuotaIncreaseRequest(
            @Valid @RequestBody QuotaIncreaseRequestDTO requestDTO,
            @AuthenticationPrincipal Jwt principal) {

and then I get the following exception pasted below.

But, if I remove the 2nd argument, and use SecurityContextHolder instead, it works.

This method does require authentication.

Update (a day later): I just changed the argument to: Principal principal and this works.

java.lang.IllegalArgumentException: tokenValue cannot be empty
    at org.springframework.util.Assert.hasText(Assert.java:284) ~[spring-core-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.security.oauth2.core.AbstractOAuth2Token.<init>(AbstractOAuth2Token.java:55) ~[spring-security-oauth2-core-5.3.2.RELEASE.jar:5.3.2.RELEASE]
    at org.springframework.security.oauth2.jwt.Jwt.<init>(Jwt.java:69) ~[spring-security-oauth2-jose-5.3.2.RELEASE.jar:5.3.2.RELEASE]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) ~[na:na]
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481) ~[na:na]
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:204) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at ...
1 Answers

Just as an example for deriving values from JwtAuthenticationToken via the @AuthenticationPrincipal does not work (Thanks @Matt F.), so I used this instead:

public ResponseEntity<xxResponse> performXXXRequest (final @AuthenticationPrincipal Jwt principal, final @RequestBody XXDTO xxDTO){
.....
}

This works:

public ResponseEntity<xxResponse> performXXXRequest (final Principal principal, @RequestBody final XXDTO xxDTO){
.....
}

//To derive Claims or other JWT details like this:
    private String resolveCallerIdFromJwtPrincipal(final Principal principal) {
        JwtAuthenticationToken jwtAuthToken = (JwtAuthenticationToken) principal;
        Jwt jwtPrincipal = (Jwt) jwtAuthToken.getPrincipal();
        return jwtPrincipal.getClaimAsString("name");
    }
Related