jjwt v0.4 Release Notes

    • Issue 8: Add ability to find signing key by inspecting the JWS values before verifying the signature.

    📜 This is a handy little feature. If you need to parse a signed JWT (a JWS) and you don't know which signing key was used to sign it, you can now use the new SigningKeyResolver concept.

    A SigningKeyresolver can inspect the JWS header and body (Claims or String) before the JWS signature is verified. By inspecting the data, you can find the key and return it, and the parser will use the returned key to validate the signature. For example:

    SigningKeyResolver resolver = new MySigningKeyResolver();
    
    Jws<Claims> jws = Jwts.parser().setSigningKeyResolver(resolver).parseClaimsJws(compact);
    

    👀 The signature is still validated, and the JWT instance will still not be returned if the jwt string is invalid, as expected. You just get to 'see' the JWT data for key discovery before the parser validates. Nice.

    This of course requires that you put some sort of information in the JWS when you create it so that your SigningKeyResolver implementation can look at it later and look up the key. The standard way to do this is to use the JWS kid ('key id') field, for example:

    Jwts.builder().setHeaderParam("kid", your_signing_key_id_NOT_THE_SECRET).build();
    

    0️⃣ You could of course set any other header parameter or claims parameter instead of setting kid if you want - that's just the default field reserved for signing key identification. If you can locate the signing key based on other information in the header or claims, you don't need to set the kid field - just make sure your resolver implementation knows how to look up the key.

    Finally, a nice SigningKeyResolverAdapter is provided to allow you to write quick and simple subclasses or anonymous classes instead of having to implement the SigningKeyResolver interface directly. For example:

    Jws<Claims> jws = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
            @Override
            public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
                //inspect the header or claims, lookup and return the signing key
                String keyId = header.getKeyId(); //or any other field that you need to inspect
                return getSigningKey(keyId); //implement me
            }})
        .parseClaimsJws(compact);