RSA256/JWKS JWT validation using Auth0's `java-jwt` and `jwks-rsa-java`

Hello,

I am attempting to learn the Auth0 developed java-jwt and jwks-rsa-java Java APIs with the eventual goal of implementing them within multiple server applications intended to act as resource owners.

We wish to use RSA256 and dinamicaly recover the the JSON Web Key Set (JWKS) from a remote authorisation server end-point as a means of validating a tokent’s signature.

To this end, I am writing a very simple java application that does the following:

  1. Decode and read a supplied access_token
  2. Retrieve JWKS from our test tenant (https://{tenant.url}/.well-known/jwks.json) using jwks-rsa-java.
  3. Use the JWKS to validate the signature within the access_token.

I am struggling with the last part.

For the purposes of this thread, lets assume the token is initially stored within a java.lang.String object called authZ_token.

Because I’m using RSA256, the first thing I’m going to need to do is retrieve the JWKS key ID (kid).

DecodedJWT decodedJwt = JWT.decode(authZ_token);
String kid = decodedJwt.getKeyId());

The above code also provides me with a DecodedJWT, so I can also use it to look at the payload and validate claims if need be.

Here is my code for retrieving the JWKS (simple enough):

JwkProvider jwkProvider = new UrlJwkProvider("https://{tenant.url.auth0.com}/");

Jwk jwk;
List<String> x5cArray;
String x5cString;

try {
	jwk = jwkProvider.get(kid);
	x5cArray = jwk.getCertificateChain();
	x5cString = x5cArray.get(0);
  
  System.out.println("x5c: " + x5cString);
} catch (JwkException e) {
	e.printStackTrace();
	throw new ServletException(e.getMessage());
}

So far so good, but here is where I run into trouble as I still have not validated the access_token signature.

The java-jwt readme indicates that I need to instantiate a JWTVerifier using a RSAAlgorithm as indicated below:

RSAPublicKey publicKey = //Get the key instance
RSAPrivateKey privateKey = //Get the key instance
try {
    Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
    JWTVerifier verifier = JWT.require(algorithm)
        .withIssuer("auth0")
        .build(); //Reusable verifier instance
    DecodedJWT jwt = verifier.verify(access_token);
} catch (JWTVerificationException exception){
    //Invalid signature/claims
}

My difficulty is in instantiating this JWTVerifier object using the data recovered in the JWKS rather than using a public/private key pair as indicated in the example above as I wish to avoid placing private keys on our resource servers.

Any help would be appreciated.

Kind regards,
Aitzol

Sources:

Hey aitzol.casado. I think you should do something like this in order to verify the JWT signature.

 DecodedJWT jwt = JWT.decode(token);        
 JwkProvider provider = new UrlJwkProvider("https://<your-domain>auth0.com/.well-known/jwks.json");
 Jwk jwk = provider.get(jwt.getKeyId());
 Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(),null);

 algorithm.verify(jwt);
2 Likes

Please let me know below is a correct way to verify the token (including expiration and claims):

private String issuer = https://your-domain.auth0.com/;

DecodedJWT decodedJwt = JWT.decode(accessToken);
JwkProvider jwkProvider = new JwkProviderBuilder(issuer).build();
Jwk jwk = jwkProvider.get(decodedJwt.getKeyId());
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);

Verification verifier = JWT.require(algorithm);
verifier.build().verify(decodedJwt);

I’m still learning, I’d appreciate any comments.
Thank you

2 Likes

Hey there!

Sorry for such huge delay in response! We’re doing our best in providing you with best developer support experience out there, but sometimes our bandwidth is not enough comparing to the number of incoming questions.

Wanted to reach out to know if you still require further assistance?