'Confused about Spring Security Jwt token builder - why do I have to pass headers and claims?
I have a scenario where a get an access token in my service, and then want to store this in Springs SecurityContextHolder. This is what I'm currently doing
SecurityContext context = SecurityContextHolder.createEmptyContext();
String accessToken = cognitoService.AccessToken();
Authentication authentication =
new JwtAuthenticationToken(Jwt.withTokenValue(accessToken)
.header("alg", "none")
.claim("scope", "message:read")
.build());
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
This works fine, but what I'm confused about is the fact that I have to pass both header and claim when creating the token. I'm thinking that both of those are already in the token I pass to .withTokenValue(...), so why do I have to specify them again? When I try doing this:
Jwt.withTokenValue(accessToken).build()
I get an exception complaining that I have to pass headers. (and if I pass headers, another exception saying I have to pass claims).
Feels like I'm missing something here? Can someone clarify?
Solution 1:[1]
I just ran into the same conundrum. Digging inside the Spring Security code, it looks like the way to do this is by using an implementation of org.springframework.security.oauth2.jwt.JwtDecoder.
In my case, I have a duel security config setup that accepts tokens from Cognito and my own JWT provider which uses Nimbus Jose. I used the Spring config based JwtDecoder for the external system and I added a hand made NumbusJwtDecoder inside my custom "JwtProvider"...here's a sample of what you can do:
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
byte[] secretBytes = myTokenSecretString.getBytes();
MACSigner macSigner = new MACSigner(secretBytes);
//I have the following as class members in my real code
JWSSigner signer = macSigner;
JWSVerifier verifier = new MACVerifier(secretBytes);
JwtDecoder jwtDecoder = NimbusJwtDecoder.withSecretKey(macSigner.getSecretKey()).build();
From here, all you really need is
Jwt jwt = jwtDecoder.decode(myJwtString);
And now you don't need to worry about manually trying to piece together a JWT instance.
As for the Cognito parser, I'm using the following config to have Spring generate the JwtDecoder for me.
requires dependency: org.springframework.boot:spring-boot-starter-oauth2-resource-server
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://cognito-idp.us-east-1.amazonaws.com/${security.oauth2.user-pool}/.well-known/jwks.json
Then you can just autowire in the JwtDecoderfor your inbound Cognito tokens and call the same jwtDecoder.decode(jwtString)to get the Jwt.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
