Auth0: Validating id_token/JWT on UI (javascript) level

Viewed 665

Update March 2019

I just went over this question again; the Auth0's github code has been updated in December 2018. They are now storing 'access_token','id_token' and 'expire_at' into the object/session, instead of localstorage and using now an 'isLoggedIn' flag to mark if authenticated or not. Check the pull request and these 2 lines in the specific commit: line1 and line2.

If you do not need to re-validate 'id_token' - like I was doing in the original question - that might be an alternative. Otherwise check original question.


Original Question

We are using auth0 for one of our clients. One stack that we are using it for is:

  • React/Redux UI
  • NodeJS backend

So we are using a cross origin authentication using implicit grant for that, using JWT with an RS256 algorithm. We also refresh tokens in background using silent authentication.

I was able to validate 'access_token' on the API (nodejs) side using node-jwks-rsa for express

On the UI level, after going through the source code of the auth0-js library I noticed that the "parseHash" method used in their provided react samples, actually validates tokens before we store them in localstorage, ie on successful authentication. Mainly this line in the source code.

Then I used their sample code that allows us to check if a user is authenticated, method isAuthenticated().

Problem with the isAuthenticated() method

From a security perspective, if later on (post authentication) a user of the application decided to manually modify the 'expire_at' label in the storage, they could get away as indeed authenticated. While of course there is additional security checking in our app, I wanted to update this function to validate 'id_token'. So far, I couldn't find any example in auth0's online docs for how to do that.

After digging in their source code I found a method validateToken that is being used. So I decided to leverage it in one of our functions:

import IdTokenVerifier from 'idtoken-verifier'
.... Some code in here ....

reValidateToken() {
  return new Promise((resolve, reject) => {
    // Both of these are stored in localstorage on successful authentication, using the parseHash method
    let id_token = localStorage.getItem('id_token');
    let transactionNonce = localStorage.getItem('app_nonce');

    this.webAuth.validateToken(id_token, transactionNonce, function(
        validationError,
        payload
    ) {
        if (!validationError) {
            resolve('no validation errors for id_token');
        }

        if (validationError.error !== 'invalid_token') {
            reject(validationError.error);
        }

        // if it's an invalid_token error, decode the token
        var decodedToken = new IdTokenVerifier().decode(id_token);

        // if the alg is not HS256, return the raw error
        if (decodedToken.header.alg !== 'HS256') {
            reject(validationError);
        }
    });
  });
}`

Now, for it to succeed; we store the nonce in localstorage after successful authentication, does this approach create back doors for potential security holes? if it does; what is best practice to validate RS256 JWT id_token(s) on a UI level?

0 Answers
Related