There are many use cases to use getAccessTokenSilently
outside of a component (for example, in an Axios Interceptor or an Apollo Client).
It's tempting to ask for the option to pass an Auth0Client
instance into the Auth0Provider
so that its getTokenSilently
method can used outside of the context of a component, eg.
const client = new Auth0Client();
export const getAccessToken = () => client.getTokenSilently();
ReactDOM.render(
<Auth0Provider client={client}>
<App />
</Auth0Provider>,
document.getElementById('app')
);
We don't expose the client or allow a custom client to be passed into the Auth0Provider
for a couple of reasons:
- We don't think you should export a singleton client from a module and risk sharing the autenticated state between requests in an SSR app - even though you might only be writing a client rendered app.
- The client's methods don't always act the same as the hooks, eg the client's
getTokenSilently
behaves differently to theuseAuth0
hook'sgetAccessTokenSilently
, and this is the same (or could be the same in future) for other methods and properties. Having a client and hook in your app would lead to inconsistencies and subtly complex bugs.
Our recommended approach is to stick with React Context API, if you have an Apollo or Axios Client, create a provider for them and nest it in the Auth0Provider
so it can have access to the useAuth0
hook to call getAccessTokenSilently
eg.
ReactDOM.render(
<React.StrictMode>
<Auth0Provider>
{() => {
const { getAccessTokenSilently } = useAuth0();
const instance = axios.create()
instance.interceptors.request.use(function () {/* use getAccessTokenSilently */});
return (
<AxiosProvider axios={instance}>
<App />
</AxiosProvider>)
}}
</Auth0Provider>
</React.StrictMode>,
document.getElementById('root')
);
If you really have to break out of React Context, you can always create a static getAccessToken
method (with the above caveats) - you don't need a static client.
const deferred = (() => {
const props = {};
props.promise = new Promise((resolve) => props.resolve = resolve);
return props;
})();
export const getAccessToken = async () => {
const getToken = await deferred.promise;
return getToken();
}
ReactDOM.render(
<Auth0Provider clientId={clientId} domain={domain}>
<Auth0Context.Consumer>
{({ getAccessTokenSilently }: any) => {
deferred.resolve(getAccessTokenSilently);
return <App />;
}}
</Auth0Context.Consumer>
</Auth0Provider>,
document.getElementById('app')
);
Is it expected that you get a different token every time you call getAccessTokenSilently from outside of React Context?
I thought that the getAccessTokenSilently would only return a different token when the current one expires.