Fun with Auth0, React and tokens
I am working on a React-based Single-Page App (SPA) using Auth0 for authentication. For a while, I have been maintaining my own little helper library to do this. It uses the auth0/auth0-js
library (which is described as “Client Side JavaScript toolkit for Auth0 API”) under the hood.
I’ve been aware of a new-ish recommended way to work with Auth0 for a while, and finally decided to migrate my sloppy integration over. I first started with auth0/auth0-spa-js
, but soon realized that Auth0 maintains a React SDK, which uses auth0-spa-js
under the hood, so I went with auth0/auth0-react
instead.
Most of the steps are pretty straightforward as documented in this quick start guide. The part I struggled with the most was getting the Access Token to call a backend API.
Before, in my sloppy integration, I was using the ID token returned from the OAuth flow to call my backend API. It is actually a bad/ wrong implementation, as called out by Auth0 tokens documentation:
Do not use ID tokens to gain access to an API.
So in order to get a proper access token, I have the following code in the App.jsx
component.
import React, { useState, useEffect } from 'react';
import { useAuth0 } from '@auth0/auth0-react';
function App() {
const [token, setToken] = useState();
const { getAccessTokenSilently } = useAuth0();
useEffect(() => {
(async () => {
const accessToken = await getAccessTokenSilently();
setToken(accessToken);
})();
});
}
However, I could not understand why the accessToken
I received was not in JWT format, but a small string of maybe 15 characters. It wasn’t a Bearer token I could use to make XHR call against the REST API server.
The Auth0 doc page on Access Tokens mentions 2 different kinds – “opaque” and “JWT”, but it didn’t mention how to get the JWT token. I was guessing that the small token I got back was the opaque token.
Not able to find any reference to this issue online, I randomly tried adding the audience
to the call to get the token, which turned out to be exactly the missing piece for me.
const token = await getAccessTokensSilently({
audience: 'https://myapi.com'
})
In hindsight, I’m guessing I was getting the opaque token because by default, Auth0 was returning the access token needed for the /userinfo
endpoint only. If anyone knows the answer to this, I would love to know.
UPDATE: This behavior is documented in this post https://community.auth0.com/t/why-is-my-access-token-not-a-jwt-opaque-token/31028
comments powered by DisqusIn order to receive a JWT you must include an
audience
parameter with your token request.