Refactor KeyProvider to receive the "Key Id" by lbalmaceda · Pull Request #167 · auth0/java-jwt · GitHub
Skip to content

Refactor KeyProvider to receive the "Key Id"#167

Merged
hzalaz merged 6 commits into
masterfrom
add-keyprovider-kid
May 4, 2017
Merged

Refactor KeyProvider to receive the "Key Id"#167
hzalaz merged 6 commits into
masterfrom
add-keyprovider-kid

Conversation

@lbalmaceda

@lbalmaceda lbalmaceda commented Apr 20, 2017

Copy link
Copy Markdown
Contributor

This PR introduces changes to better support Key Rotation.

Super classes

JWT no longer implements DecodedJWT. Users who find this breaking need to update the return type of JWT.decode() and JWT.require() ... verify() to DecodedJWT instead of JWT.

JWT parts

Before this PR the DecodedJWT instance just allowed to obtain the original version of the token and the signature (third part). Now 2 more methods were added: getHeader() and getPayload() which return the first and second part of the header as it is, with a Base64 encoding.

KeyProvider refactor

Now receives a "Key Id" when asked for the PublicKey, and also asks for a "Signing Key Id" that will be set in the header of the token in the signing process. If the "Key Id" is being set by the user using the withKeyId() in the JWTCreator class, the library won't overwrite it with the one defined in the KeyProvider implementation.
Users who doesn't use KeyProvider (i.e. instantiate the algorithm by passing just the keys) or return null in the getSigningKeyId() call will not be affected by this and the kid claim won't be automatically set.

Example usage:

final MyOwnJwkProvider jwkProvider = new MyOwnJwkProvider("{JWKS_FILE_HOST}");
final RSAPrivateKey privateKey = //Get the key instance
final String privateKeyId = //Create an Id for the above key

RSAKeyProvider keyProvider = new RSAKeyProvider() {
    @Override
    public RSAPublicKey getPublicKeyById(String kid) {
        //Value might be null if it wasn't defined in the Token's header
        Jwk jwk = jwkProvider.get(keyId);
        return (RSAPublicKey) jwk.getPublicKey();
    }

    @Override
    public RSAPrivateKey getPrivateKey() {
        return privateKey;
    }
    
    @Override
    public String getPrivateKeyId() {
        return privateKeyId;
    }
};
Algorithm algorithm = Algorithm.RSA256(keyProvider);
//Use the Algorithm to create and verify JWTs.

Algorithms

The Algorithm#verify method changed it's signature: Now it will verify a given DecodedJWT instance instead of the byte[] of signature and contents. This was needed to get the "Key Id" claim and request it's associated PublicKey to the KeyProvider. Although this is a breaking change, users shouldn't be using the Algorithm class directly as it's purpose is to be called internally by the library.

Comment thread README.md Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By using a KeyProvider you can in runtime change either the key used to verify the token signature or to sign a new token for RSA or ECDSA algorithms. This is achieved by implementing either RSAKeyProvider or ECDSAKeyProvider methods:

  • getPublicKeyById(String kid): Its called during token signature verification and it should return the key used to verify the token. If key rotation is being used, e.g. JWK it can fetch the correct rotation key using the id. (Or just return the same key all the time).
  • getPrivateKey(): Its called during token signing and the key will be used to sign the JWT.
  • getPrivateKeyId(): Its called during token signing and it should return the id of the key that identifies the one returned by getPrivateKey()

Comment thread README.md

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below this we can add a note saying that they could use jwks-rsa-java to perform the jwk handling

@lbalmaceda lbalmaceda requested a review from nikolaseu May 3, 2017 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants