Java – JJWT parsing does not fail if the SigningKey is slightly different

JJWT parsing does not fail if the SigningKey is slightly different… here is a solution to the problem.

JJWT parsing does not fail if the SigningKey is slightly different

I tried to create a JWT token

final String jws = Jwts.builder()
            .claim("rainId", rainId.toString())
            .signWith(SignatureAlgorithm.HS256, TextCodec.BASE64.decode("jwtSecretKey"))
            .compact();

Then I tried to parse it

Jws<Claims> jwsClaims = Jwts.parser()
                .require("rainId", rainId.toString())
                .setSigningKey(TextCodec.BASE64.decode("jwtSecretKey1"))
                .parseClaimsJws(jws);

As you can see, SigningKey is slightly different, so I expected the parser to fail, but it didn’t happen. This only happens if there is a big difference in the SigningKey in the parser. For example, “jwtSecretKey1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 If the SigningKey in the parser is slightly different, can someone explain why the parser doesn’t fail?

I use

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>

Solution

You don’t seem to be using the API properly.

Both the signWith() and setSigningKey() methods require a Base64-encoded string as input. But you are calling TextCodec.BASE64.decode("...").

Neither jwtSecretKey nor jwtSecretKey1 looks like a Base64-encoded string. However, if you try to decode them, they will produce the same output:

System.out.println(Arrays.toString(TextCodec.BASE64.decode("jwtSecretKey")));
System.out.println(Arrays.toString(TextCodec.BASE64.decode("jwtSecretKey1")));
[-113, 11, 82, 121, -54, -34, -76, -89, -78]
[-113, 11, 82, 121, -54, -34, -76, -89, -78]

This is why signature verification does not fail.

You should use TextCodec.BASE64.encode("...") instead, as follows:

String jws = Jwts.builder()
        .claim("rainId", rainId.toString())
        .signWith(SignatureAlgorithm.HS256, TextCodec.BASE64.encode("jwtSecretKey"))
        .compact();

Jws<Claims> jwsClaims = Jwts.parser()
        .require("rainId",rainId.toString())
        .setSigningKey(TextCodec.BASE64.encode("jwtSecretKey1"))
        .parseClaimsJws(jws);

Related Problems and Solutions