Describe the bug
In Spring Security 7, a NimbusJwtEncoder constructed by private NimbusJwtEncoder(JWK jwk) produces Jwt objects with incorrent "typ" parameter values in headers. The "typ" header parameter should declare the media type of the complete JWT and the value should be "JWT" in most cases, as is defined in RFC 7519. However, the value emitted by NimbusJwtEncoder is acutally the type of the signing JWK, i.e. the "kty" value defined in RFC 7517, whose common values include "RSA", "EC", "oct", etc.
Such an incorrect "typ" value is rejected by JwtTypeValidator.jwt(), which is employed by NimbusJwtDeocder by default in Spring Security 7, causing a JWT verification error.
This bug was introduced in Line 139 below, where jwk.getKeyType() was passed to JwsHeader.Builder#type(String type):
|
private NimbusJwtEncoder(JWK jwk) { |
|
Assert.notNull(jwk, "jwk cannot be null"); |
|
this.jwkSource = new ImmutableJWKSet<>(new JWKSet(jwk)); |
|
JwsAlgorithm algorithm = SignatureAlgorithm.from(jwk.getAlgorithm().getName()); |
|
if (algorithm == null) { |
|
algorithm = MacAlgorithm.from(jwk.getAlgorithm().getName()); |
|
} |
|
Assert.notNull(algorithm, "Failed to derive supported algorithm from " + jwk.getAlgorithm()); |
|
JwsHeader.Builder builder = JwsHeader.with(algorithm).type(jwk.getKeyType().getValue()).keyId(jwk.getKeyID()); |
To Reproduce
-
Create a NimbusJwtEncoder instance using SecretKeyJwtEncoderBuilder (You may also use RsaKeyPairJwtEncoderBuilder or EcKeyPairJwtEncoderBuilder, as long as the private constructor is invoked):
SecretKey secretKey = KeyGenerator.getInstance("HmacSHA256").generateKey();
NimbusJwtEncoder jwtEncoder = NimbusJwtEncoder.withSecretkey(secretKey).build();
-
Encode a JWT with the NimbusJwtEncoder instance:
JwtClaimsSet claims = TestJwtClaimsSets.jwtClaimsSet().build();
Jwt jwt = jwtEncoder.encode(JwtEncoderParamaters.from(claims));
-
Print out the "typ" parameter value, and you'll see oct —— the "kty" of a HS256 JWK.
System.out.println(jwt.getHeaders().get(JoseHeaderNames.TYP)); // It prints: oct
Expected behavior
The expected value of the "typ" header parameter is often "JWT". If RFC 9068 is anticipated it may be "at+jwt".
Sample
I was surprised by the fact that this bug hasn't been caught by existing tests, so I created a symmetric test NimbusJwtEncoderDecoderTests.java where a JWT encoded with NimbusJwtEncoder is then decoded with NimbusJwtDecoder. With a JwtTypeValidator included in JwtValidators.createDefault(), NimbusJwtDecoder throws a JwtValidationException, saying:
An error occurred while attempting to decode the Jwt: the given typ value needs to be one of [JWT]
Describe the bug
In Spring Security 7, a
NimbusJwtEncoderconstructed byprivate NimbusJwtEncoder(JWK jwk)producesJwtobjects with incorrent"typ"parameter values in headers. The"typ"header parameter should declare the media type of the complete JWT and the value should be"JWT"in most cases, as is defined in RFC 7519. However, the value emitted byNimbusJwtEncoderis acutally the type of the signing JWK, i.e. the"kty"value defined in RFC 7517, whose common values include"RSA","EC","oct", etc.Such an incorrect
"typ"value is rejected byJwtTypeValidator.jwt(), which is employed byNimbusJwtDeocderby default in Spring Security 7, causing a JWT verification error.This bug was introduced in Line 139 below, where
jwk.getKeyType()was passed toJwsHeader.Builder#type(String type):spring-security/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java
Lines 131 to 139 in 676b44e
To Reproduce
Create a
NimbusJwtEncoderinstance usingSecretKeyJwtEncoderBuilder(You may also useRsaKeyPairJwtEncoderBuilderorEcKeyPairJwtEncoderBuilder, as long as the private constructor is invoked):Encode a JWT with the
NimbusJwtEncoderinstance:Print out the
"typ"parameter value, and you'll seeoct—— the"kty"of a HS256 JWK.Expected behavior
The expected value of the
"typ"header parameter is often"JWT". If RFC 9068 is anticipated it may be"at+jwt".Sample
I was surprised by the fact that this bug hasn't been caught by existing tests, so I created a symmetric test NimbusJwtEncoderDecoderTests.java where a JWT encoded with
NimbusJwtEncoderis then decoded withNimbusJwtDecoder. With aJwtTypeValidatorincluded inJwtValidators.createDefault(),NimbusJwtDecoderthrows aJwtValidationException, saying: