Continue Discussion 168 replies
July 2020

avala

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.

2 replies
July 2020 ▶ avala

dan-auth0 Auth0 Employee

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:

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 replies
July 2020 ▶ dan-auth0

avala

@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

July 2020 ▶ dan-auth0

avala

@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 reply
July 2020

macm

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 reply
July 2020 ▶ avala

dan-auth0 Auth0 Employee

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

July 2020 ▶ macm

dan-auth0 Auth0 Employee

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:

July 2020

dc.gaudium

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?

1 reply
July 2020 ▶ dc.gaudium

dan-auth0 Auth0 Employee

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.

August 2020

solace

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 reply
August 2020 ▶ solace

dan-auth0 Auth0 Employee

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:

1 reply
August 2020 ▶ dan-auth0

solace

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

1 reply
August 2020

asdFletcher

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 reply
August 2020

konrad.sopala Community Engineer

Hey there!

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

August 2020

dan-auth0 Auth0 Employee

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.

1 reply
August 2020 ▶ solace

dan-auth0 Auth0 Employee

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?

1 reply
August 2020 ▶ dan-auth0

solace

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 reply
August 2020 ▶ dan-auth0

asdFletcher

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?

2 replies
August 2020 ▶ asdFletcher

dan-auth0 Auth0 Employee

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

August 2020

m.j.j.golda

Hi, I used React Auth0 SDK according to The Complete Guide to React User Authentication with Auth0 with my custom app. Everything seems to be fine.

However when I open react dev tools in chrome I can modify Auth0Provider state so I can change reducer and isAuthenticated to true. This enable me to get into app without login and protected routes are also not protected as long as you reload app. I set also devtools to false in webpack.

Can I somehow protect this state in react devtools??

Thanks

August 2020

konrad.sopala Community Engineer

Moving your topic to this thread as this is the one to raise questions and issues regarding this blog article.

1 reply
August 2020 ▶ konrad.sopala

m.j.j.golda

Thank you.

I turned off react dev tools for my production build.
However I am curious if you have other solution for this issue?
Otherwise it would be nice to warn users about enabling React dev tools in their app.

It looks like security bug in React SDK.

2 replies
August 2020 ▶ m.j.j.golda

dan-auth0 Auth0 Employee

Howdy, Marcin. Welcome to the Auth0 Community. Thank you for reading the blog post and for sharing this feedback.

I’ll share your question with the team who developed the SDK and get back to you as soon as I have an answer :+1:

August 2020 ▶ m.j.j.golda

dan-auth0 Auth0 Employee

Hey, Marcin. I did some research about your concern. In essence, it is safe to assume that any of the client-side code can be modified as it publicly accessible. As mentioned in the post, the client-side routing is implemented for UX purposes and not for security purposes.

We should not see the client-side router as a mechanism to securely gate content but rather as a tool for navigation and information presentation.

You secure data in a SPA by putting it behind an API that is protected by an access token. Any content you deploy with your SPA will be visible to anonymous users who can find it using the browser dev tools or by viewing its source. I checked with the team and we determined that the ability to change the value of the Auth0Provider is not a security bug.

If you decide to keep the React DevTools on for production and a user manipulates the state of the provider, then whenever they make their way into pages that would show protected information, they should see error messages or blanks.

1 reply
August 2020

dan-auth0 Auth0 Employee

Howdy, asdFletcher!

I consulted with our engineer @luciano.balmaceda to come up with the following answer. Thanks, Lucho!

If you open http://jwt.io/, replace what is on the left by the following:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6InJlYWQ6eCx3cml0ZTp4In0.V43LGfx51FDmy4HPPRTZQUE8lfXWUglb9arCREWqn74

You get the following decoded payload:

{
  "scope": "read:x,write:x"
}

Now, change the scope of the payload. For example, add an entry:

{
  "scope": "read:x,write:x, data:admin"
}

Notice how the signature of the access token on the left changes: Weg6q1N4WawkuQBh6OZdSKtp3gTs1VUfe4AQIvHHhuc.

Now that you have changed the scope, replace the blue part of the access token on the left (the signature) with the signature the original token had: V43LGfx51FDmy4HPPRTZQUE8lfXWUglb9arCREWqn74

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6InJlYWQ6eCx3cml0ZTp4LCBkYXRhOmFkbWluIn0.V43LGfx51FDmy4HPPRTZQUE8lfXWUglb9arCREWqn74

Look below the token box and notice how it says “Invalid Signature”. When you use the original signature but change the scopes, the token becomes invalid. If you were to send that token in the authorization header of a request to your API, it would reject the request as the token is invalid.

The access token in JWT format is public but you cannot change the content of the header or the body without changing the signature.

This is how it works in practice:

  1. The user logs in to your app on a mobile phone and gets an access token with the audience to consume your backend API. The Auth0 authorization server signed that access token using a private key or client secret.

  2. The user makes a request to your API passing the token it got from Auth0 in the authorization header, without changing it.

  3. Your API verifies that the access token signature matches using a client secret or public key to recalculate the signature in the backend.

  4. If the token is valid, has a valid audience, and has the required permissions to access the requested endpoint, the request goes through and the server replies to the user.

To explain the concept of “Auth0 APIs” and how the audience helps this whole process, I’ll link to this amazing answer by @nicolas_sabena:

Please let me know if you have any further questions! This was a great question! Thank you for asking it.