Invalid access token returned when using refresh token

Ready to post? :mag: First, try searching for your answer.
I’ve got a react app with a nodejs backend and a cloud database. I’m new to auth0 to trying to get it all setup. I had simple user authentication setup using the react API no problem. Now I’m trying to use refresh tokens with shorter access token expiration times, to hopefully make it more secure.

I have middleware that checks the expiration date of the authorization access token coming into my axios calls. If they are expired I was planning to use the refresh token to get new access tokens. I can use the refresh token from my database to get new tokens as follows:
tokenData: {
access_token: ‘…’,
refresh_token: ‘…’,
id_token: ‘…’,
scope: ‘openid profile offline_access’,
expired_in: xxxx,
token_type: ‘Bearer’
}

I store the new refresh token in my database and try to replace the authorization access token in the axios header with the new one:
req.headers.authorization = Bearer ${newTokens.access_token};

And was hoping everything would continue, however it appears the access token I receive back is malformed, or it might be a JWE (encrypted) toke? Either way, when I try and use it as is, I get errors saying it is an invalid token.

Any help is appreciated!

To make sure my configuration is clear:

<Auth0Provider
      domain={auth0data.domain}
      clientId={auth0data.clientId}
      authorizationParams={{
        audience: auth0data.audience,
      }}
>

Here is my client side call to authorize when I hit the login button, it includes the code challenge and setting the scope to include offline_access:

'https://'+ auth0data.domain + '/authorize?' +
      'response_type=code&' +
      'client_id='+ auth0data.clientId + '&' +
      'redirect_uri='+ auth0data.redirectURL + '&' +
      'code_challenge='+ codeChallenge + '&' +
      'code_challenge_method=S256&' +
      'scope=offline_access openid profile';

My callback captures the authorization code and sends it to the back end, along with the code verifier.
const params = new URLSearchParams(location.search);
const authorizationCode = params.get(‘code’);
const response = await axios.post(baseUrl + channels.AUTH0_GET_TOKENS,
{ authorizationCode: authorizationCode, codeVerifier: codeVerifier });

Back end then makes the call to get the tokens:

const tokenResponse = await `https://${process.env.REACT_APP_AUTH0_DOMAIN}/oauth/token`, {
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
           grant_type: 'authorization_code',
           client_id: process.env.REACT_APP_AUTH0_CLIENT_ID,
           client_secret: process.env.REACT_APP_AUTH0_CLIENT_SECRET,
           code: authorizationCode,
           redirect_uri: process.env.REACT_APP_AUTH0_CALLBACK_URL,
           code_verifier: codeVerifier,
    }),
}

I wasn’t sure how to store the access token back on the client side. So once the back end returns back to the client side, I was setting the client side authentication as follows. This seems to work, but I’m sure there is a better way.

loginWithRedirect({
  authorizationParams: {
    response_type: 'token',
    client_id: auth0data.clientId,
    redirect_uri: `${window.location.origin}`,
    audience: auth0data.audience,
    scope: 'read:current_user',
  },
});

When I detect that an access token has expired, I

`https://${process.env.REACT_APP_AUTH0_DOMAIN}/oauth/token`, {
  grant_type: 'refresh_token',
  client_id: process.env.REACT_APP_AUTH0_CLIENT_ID,
  client_secret: process.env.REACT_APP_AUTH0_CLIENT_SECRET,
  refresh_token: refreshToken,
}
1 Like