Auth0 Home Blog Docs

Problem validating JWT with X509 cert/pubkey from /jwks

api
certificate
jwt-validation

#1

I am trying to implement my server side JWT access token validation (in java) into my API code using a restful service filter. I have my authorization bearer access_token for my audience and I have my signing certificate string from the client-advanced-setting-certificate in the auth0 UI (or from the downloaded .PEM file)

If I put the token and the certificate into jwt.io if all looks good and the certificate validates the jwt

for the time being I am just trying to get it to execute once in the API to see it work with the String object called cert in the code
if I call my url https://myclient.auth0.com/.well-known/jwks.json to I get the json and the “x5c”: claim and I take that text and put it into a the string variable cert in my java code (or I take the string from the PEM file and either strip the header and footer or not)

	            byte[] keyBytes = Base64.decode(cert);
	            X509EncodedKeySpec spec =
	              new X509EncodedKeySpec(keyBytes);
	            KeyFactory kf = KeyFactory.getInstance("RSA");
	            PublicKey publicKey = kf.generatePublic(spec);

this generates this exception :
java.security.InvalidKeyException: IOException: ObjectIdentifier() – data isn’t an object ID (tag = -96)

I am trying to get the public key because I need it to validate the signature using the jjwt java library
which I chose over the Auth0 library because github indicated the latest build for java-jwt is failing ?
although I had some difficulty integrating the jjwt library into my eclipse projects as well.

I assume I will need the public key from the cert even if I switch to the auth0 library

Also I have run some test code from github that executes the same process, a diff pair of token and cert strings it executes fine, but not the ones I need to work with (and that work in jwt.io)

What am I doing wrong or understanding incorrectly ???
Is there any sample code in Java showing the extraction of the cert and public key from the /jwks.json endpoint and then converting the x5c to the java objects needed to perform the validation and signature verification ?
I looked all over and couldn’t find much

thanks


#2

Hi Amalycky,

You can extract the public key from x5c certificate. Using this online tool, convert your x5c string to a valid x509 certificate. Then extract public key with openssl:

openssl x509 -in x5c-cert-formated.pem -pubkey -noout > public-key.pem

Then in your Java code:

         // strip of header, footer, newlines, whitespaces
         String publicKeyPEM = key
                 .replace("-----BEGIN PUBLIC KEY-----", "")
                 .replace("-----END PUBLIC KEY-----", "")
                 .replaceAll("\\s", "");

         // decode to get the binary DER representation
         byte[] publicKeyDER = Base64.getDecoder().decode(publicKeyPEM);
         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyDER);

         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         return keyFactory.generatePublic(keySpec);

Hope that helps,
Amin


#3

I am running into the exact same thing as the original author. I am confused by the response provided here though.

If I am doing this all in the same process … i.e. pulling the current key from the jwks.json, they trying to get the public key from that … how do you stop in the middle of the process and use a 3rd party site to format the key and then openssl to covert it?

That seems like the missing piece in every bit of documentation or example I have found thus far - how to get the public key based upon the result of the jwks.json.

Obviously (I expect), other people have gotten through this. Any suggestions?


#4

yeah using a third party command line tool is not an option on the fly
has been a long time since I looked at this but

I was able to get the public key by doing the following where x5C is the string representation of the cert

public static PublicKey getPublicKey() 
	throws CertificateException, IOException {
	
	byte[] keyBytes = Base64.decode(x5c);
    CertificateFactory fact = CertificateFactory.getInstance("X.509");
    X509Certificate cer = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(keyBytes));
    return cer.getPublicKey();
    
}

once I had the public key it was working fine for validation of the signature

the imports were

import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

and I used the jjwt.0.9.0 jar


#5

hi Jeff. It’s a one-time activity.