The Complete Guide to React Authentication with Auth0

Auth0 launched its React SDK on June 24th, 2020, to provide React developers with an easier way to add user authentication to React applications using a hooks-centric approach.
Learn how to add user authentication to React using Context and Hooks.

Read more

Brought for you by @dan-auth0

5 Likes

This is, by far, the most comprehensive guide to getting Auth0 set up on your React project. I would have greatly appreciated this link being included in the Quick Start React guide when I was getting started.

I ran into one problem however where components making an API call with useEffect create an infinitie loop only when using Private Routes. I have a form component protected by the Private Route as setup in this guide. The form component has a useEffect hook with an empty array dependency to only run on componentDidMount. This useEffect hook calls a basic Axios.get function to populate a global context component which in turn populates our form fields. This was working before adding the Private Routes, and continues to work if using a normal route. Under the private route, the browser begins to chug and throws:

Uncaught (in promise) Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

Is there a better way to construct this? Is it possible to include an example in this guide? I’ve combed through the many different forms of React documentation, but nothing seems to blend Private routes with API calls. This seems like something that should be easy to setup.

3 Likes

Howdy, Avala. Thank you for joining the Auth0 Community and for your feedback :raised_hands:

If I understand correctly, the example that you’d like to see is as follows:

  • You have a component that makes API calls within a useEffect() hook.
  • The component stores the response from the API in a global Context component.
  • You limit access to the component by wrapping it up in a PrivateRoute Higher-Order Component.

Is that right? If so, I definitely have planned to provide an example of this in the close future.

Where it may get tricky is the following:

This useEffect hook calls a basic Axios.get function to populate a global context component which in turn populates our form fields.

This is more of an implementation detail of state management that could be done in different ways and could be the source of the performance error. For example, I default to Formik when I need to use forms in React. I have an app that has private routes to gate components with forms in them but I have not experienced an error like the one you pointed out yet, which makes me think the source of the error is not related to the presence of the PrivateRoute per se but something else :thinking:

2 Likes

@dan-auth0 Thanks for the quick response on a Friday! It looks like you have the scenario correct. I’ve tinkered with the app further and it seems like the issue stems from attempting to manipulate the Global State context. We’re using Formik as well, but have some funky use-cases with a material stepper and a repeating table that makes this project interesting.

After further testing, I can run a fetch request and update local state with expected behavior, but when we attempt to read or edit the global state context (in useEffect or a callback) the stuff hits the fan again. Long story short, attempting to dispatch to the Global State Reducer generates an infinite loop when using Private Routes, but normal Routes work fine.

image

@dan-auth0 you were completely correct. I took another look at my global context provider and refactored my app reducer and callbacks in the form. It’s working like a champ now! Thank you for this great write up!

1 Like

I have to admit this tutorial got me fast forwarded massively on getting auth0 working. Thanks Dan. Of course though I ran into issues when trying to integrate it into my react-redux app. I am wondering if you might be able to provide some insight into the following…
1: passing/getting a token when in a class based component
image

2: Setting the user profile data into a reducer and assigning the props?

1 Like

Hey, Avala! Glad to read that :tada: You are welcome, thank you for reading the guide :slight_smile:

1 Like

Howdy, Macm! Welcome to our Auth0 Community and thank you for reading the post.

With the guide that we just published, we are only scratching the surface of the React ecosystem. There are different uses cases that I am planning to cover in the coming weeks/months. The most important ones I have on my list are: React + TS version, using class components, and React + Redux.

I am in the process right now of formulating our Redux strategy, specially when the application architecture gets more complex using side effects.

In the meantime, this section of the SDK Docs, Use with a Class Component, can provide you insight on how to integrate the new Auth0 React SDK with class components :slight_smile: In a nutshell: You use the withAuth0 higher-order component that the SDK exposes to wrap your component. Then, all the SDK props are available to you through this.props.auth0.

I’ll keep this Community Topic updated as we develop more guidance for the React ecosystem :pray:

What is the difference between @auth0/auth0-spa-js and @auth0/auth0-react?

The SPA sdk is older while the React sdk is very new, but how are they different in usage and underlying implementation? Are there differences/benefits that would make it easier to use one over the other?

Also, in terms of the conversation on a previous blog post (How to Secure GatsbyJS Sites with Auth0 for Authentication), which sdk would you recommend for usage with Gatsby given that Gatsby is geared towards SPAs built with React?

2 Likes

David, that’s a great question :slight_smile: I’ll be creating much more content on React Security and Identity in the coming weeks/months and this is a use cause that I want to highlight! React SDK vs Auth0 SPA SDK.

Technically, what happens under the hood is still the same. However, prior to the introduction of the React SDK, we prompted developers to create a React Component to manage their Auth0 Authentication integration. You’d copy and paste a large section of code into a file that would be your “React SDK”.

What we did was to package all that integration into its own consumable package following the idioms of React. Now, you download the SDK and think in terms of React constructs at a high level (Hooks, Higher-Order Components) instead of having to implement authentication functionality from scratch.

You could also say that the React SDK is opinionated. We provide you with the high-level functions to power the authentication flow. If you were to use the Auth0 SPA SDK, you assemble the flow perhaps in a different way and create different hooks or wrappers.

To my knowledge, if you need to access the Auth0 Client outside of the React Realm, you may benefit from using the Auth0 SPA SDK.

Regarding Gatsby:

We are in the process of updating our Gatsby Guidance to use the new React SDK. I recommend that you try out the React SDK with Gatsby as it’s very easy to use. You can use the withAuth0 HOC to wrap the components you want to protect or you could create a private route component for the router that Gatsby uses. On my personal experience, I always ended up migrating to React Router as I find it easier to create that private route component.

Hi,

Thanks for this comprehensive guide.

I’ve set up an app which uses @auth0/auth0-react for the front-end as described, and auth0 in the back to perform management actions including updating user_metadata and email. With updating email, it requires you to log in again so that’s one workaround, but when you update metadata there doesn’t seem to be a way to update the cached user object in the front-end to reflect the changes without logging out and back in again.

Is there a way to re-fetch the user, or (less optimally) manipulate the cached data to reflect the changes?

Thanks

1 Like

Howdy, Solace! Welcome to the Auth0 Community and thank you for reading the guide! This is an excellent question. Let me consult with my team internally to see what strategy could work here :slight_smile:

Thanks. Looking forward to hear what you come up with.

I’m working through the react mega tutorial and I can now successfully login using username and password.

For curiosity’s sake, I am interested in viewing the JWT that the client receives after authentication.

Where is this JWT stored? As a developer, how do I access it?

SDK: @auth0/auth0-react 1.0.0

Thank you!

1 Like

Hey there!

Moving your message here as this si the thread related to handling issues and questions regarding that blog article. Thank you!

Howdy, asdFletcher! Check out the “Hack Yourself” section of the “Developing a Secure API with NestJS: Managing Roles” which shows you how to get the access token. Once you have the token, you can use https://jwt.io/ to decode it.

For background: the client demo app that we use in the NestJS tutorial is a React app, but this process of inspecting the access token is the same for any client app.

Just wanted to follow up with you: I am still researching what guidance we can provide on getting user metadata. Let me please ask you: how frequent do you estimate that data will change?

Thanks for checking in.

I was planning on using user_metadata for profile information such as First/Last name, and possibly settings/preferences if that helps.

If this is not a recommended use of that property let me know.

Thanks!

1 Like

Hi Dan, thanks for the quick response.

I have retrieved the client id JWT from the “token” response that I receive on authentication, I decoded it and it appears to be different from the access token I get when I call:

getAccessTokenSilently()

However, the information when decoded is the exact same. I realize there’s not really a question there.


A followup question would be, how does my node.js backend verify that the JWT is valid? All the information it has is environment variables:

AUTH0_AUDIENCE=
AUTH0_ISSUER=

How does my backend know that an authenticated client hasn’t changed scopes to include “admin”, for instance. Or is that what the secret key is for?

1 Like

You are welcome. I am putting together an answer for you in relation to token integrity and trust on its claims :slight_smile:

1 Like