Problem validating JWT with X509 cert/pubkey from /jwks

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

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

1 Like

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?

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

1 Like

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

can use this script jwks.sh.

I am seeing “io.jsonwebtoken.SignatureException : Unable to verify RSA signature using configured PublicKey. Signature length not correct: got 256 but was expecting 342” exception. I am getting the modulus and exponent to create RSAPublicKeySpec instance. The modulus is string and is not Base 64 encoded so the way i am creating instance is new RSAPublicKeySpec(new BigInteger(n.getBytes),new BigInteger(e.getBytes)). In order to create public key, i am using this RSAPublicKeySpec instance to get key instance KeyFactory.getInstance(“RSA”).generatePublic(rsaPublicKey).
Not sure if anything is wrong with the way RSAPublicKeySpec is being initialized. Any pointers will be helpful.

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?

Hey,

I was trying to validate my JWT with a my self-signed public certificate and it was not working.
After 2h of trying i decided to try to validate it using the jwt.io chrome extension and it works.

I think there was a recent update to the jwt.io website. I noticed the placeholder text in the textboxes also changed. The chrome extension still seems to be using the version before this update.

Hey there!

Thanks for reporting it. Tagging @Sambego for visibility here as he’s one of the maintainers for this website