Unable to verify jwt. generated idToken looks different than the ones generated by our other application

I’m trying to verify an idtoken issued by our new auth application, but it is failing… We also have another application on a different tenant which is working, but the idtoken looks very different.

This is a idToken issued by our working (5 years old) auth0 application:


On our backend we are verifying it and grabbing the email like so:
const result = jwt.verify(token, clientSecret, { audience: auth0ClientId });

In our new app we have create a new tenant and setup a universal login page. we are using react SPA SDK. When user logs in on our frontend through that auth0 login page, I am getting the idToken like this:

this.state.auth0Client.getIdTokenClaims().then(data => {
    const auth0Token = data.__raw;
    .... send token to be verified on backend
});

this token that I get in __raw looks different than the one we get in our other app. It looks like this:

When trying to verify this token I first got th error: invalid algorithm
I notice that this token is encoded with RS256 and not HS256 like the one issued by our other app… Why is that?

Anyway, I have tried to change the verification by parsing in an algorithm array in the options like so:

const result = jwt.verify(token, clientSecret, { audience: auth0ClientId, algorithms: ['RS256'] });

However, this also does not work I get a different error:

{
library: ‘PEM routines’,
function: ‘get_name’,
reason: ‘no start line’,
code: ‘ERR_OSSL_PEM_NO_START_LINE’
}

1. Why are the two idTokens so different, both in terms of encoding algorithm but also what they contain?
2. How can I solve this?

Hi rasmus1

You can change the content of ID tokens (and access tokens) as you want. That’s probably why they are different.

But the real issue here is the signature. I do not recommend the HS256 signature, it requires a shared private key. The RS256 algorithm does not, and you can use this endpoint: https://auth0.com/docs/tokens/concepts/jwks to get the keys you need to verify.

John

Hey John, thanks for your reply. Does that mean that our older app is less secure as it uses HS256? Where does these “shared private keys” exist? we are using the clinet secret to verify the token, that secret is encrypted and stored safely.

Regarding the keys needed to verify the RS256 encoded token, is that changing keys? or why do I need to fetch them from an endpoint? I would prefer having the decode keys stored among our other secrets to avoid additional round trips that eventually could slow down the logging in experience for the user.

Rasmus

Hi Rasmus

Not less secure, it is more painful. If a key is compromised, you must securely transport and store it at both endpoints. With RS256, the client downloads the verification key, so you don’t have to worry about that step.

Our RS256 keys do not normally change, though they can. We recommend caching them, so the effective traffic increase is zero.

John

Okay, that sounds logical. If I still wanted to continue using the HS256 algorithm, would there be a way to configure our new app to also use that encoding? …so both apps are using the same technology. Or is it deprecated and replaced with the RS256? If so, how do I do this ?

Rasmus