React Authentication By Example: React Router 6

6 posts were split to a new topic: Full Stack Architecture + Auth0

Something to add regarding passing props here…

You’ll also need to go to each individual component file where you are receiving the props and add them there on two places:

export const Dashboard = ({ addPropsHere }) => {

  return (
    <PageLayout addPropsHere={addPropsHere}>

This is if you want to pass props to the NavBar for some reason, and then you need to have the data in both the NavBar and the /route component.

1 Like

Is there any way in react router 6 to have the role based routing in react apps, mainly with “AuthenticationRequired” function.

1 Like

Hello! Welcome to the Auth0 Community. Yes, there is! I am working on a sample that may show how to do that. I may not be able to share the full-sample too soon but I can definitely share the code snippets within the next weeks.

Stay tuned, please!

1 Like

Thanks for sharing this insight with us :pray: :muscle:

1 Like

How / Where do I see logs to see an error? What’s the starting point to debug?

I am running the sample app from React Authentication By Example: Using React Router 6. (using localhost:4040)

Despite adding a User (and A) confirming the user exists in the backend, and B) making the user validate their email address)… the sample app always returns a 401 (Error - Unauthorized)

I want to figure this out, but I don’t see any useful logs anywhere. Are there any know issues w/ the Getting Started guide?

Hello! Welcome to the Auth0 Community. You can view helpful logs to debug and troubleshoot your Auth0 integration in your Tenant. Go to the Auth0 Dashboard and click on the “Monitoring” tab on the left side bar. Then click on “Logs”.

1 Like

Thanks Dan - the issue is a “Failed Exchange” after a “Success Login”

This is happening for Chrome & Firefox (desktop).

I saw a similar issue reported for an Angular SPA app back in 2020 (Success Login and a Failed Exchange - #9 by sagun786), but I do not know where those configuration settings are stored. (I did a text search for “grant_types” and “token_endpoint_auth_method” in the React sample app, but nothing came up.

Is this a common newbie problem w/ a simple fix?

Also, just to make sure I’m not missing something basic here… I set “http://localhost:4040” for the following settings:

  1. Allowed Callback URLs
  2. Allowed Logout URLs
  3. Allowed Web Origins
  4. Allowed Origins (CORS)

Hi @craigp, thanks for sharing that information. As mentioned in the issue that you just shared sounds like that error is related to the Authorization flow used when logging in. To confirm that and help you troubleshoot this issue, could you please help us with the following:

  • Share with us the type code of the “Failed Exchange” error you got. You can see the type code of it by clicking on the “Failed Exchange” event. A more detailed page of the error will show up. Under the “Details” section, you’ll see a JSON object with more details of the error. The “type” key is the type code.
  • Validate that the Auth0 Application type you’re using is a “Single Page Application”.

In case the Auth0 application you’re using is not a “Single Page Application”, do the following to change it:

  • Go to the "Settings " tab of your Auth0 application.
  • Under the "Application Propiertes " in your Auth0 application, select “Single Page Application” as the "Application type ". A confirm dialog may appear, click on "Confirm " and then click on the "Save Changes " button at the bottom of the page.

Before trying to log in again, I suggest clearing the cookies first. You can do that by navigating to the application, clicking on the information icon at the right of the address bar, and clicking on Cookies. Then remove all the cookies for this site and try to log in.

Please let us know if that works for you or if you still need help.

Hi, is there any guidance on how to perform auth checks and access the bearer token in React Router’s new loaders and actions? The challenge is these sit above/outside of the Auth0Provider component.

This was also asked here under point 2.


[Answered]

I found a good solution here using the “@auth0/auth0-spa-js” package.

Hi,

Is there a way to display a child route instead of the parent when refreshing the page?

Currently, I have the following setup:

const router = createBrowserRouter([
{
path: ‘/’,
element: ,
errorElement: ,
},
{
path: ‘/dashboard’,
element: ,
errorElement: ,
children: [
{
path: ‘new’,
element: ,
},
{
path: ‘settings’,
element: ,
},
{
path: ‘pilot’,
element: ,
},
],
},
{
path: ‘/faq’,
element: ,
},
{
path: ‘*’,
element: ,
},
]);

It works fine, except when I reload a child route. It always displays the parent dashboard page.

Note that I’m navigating to the settings and pilot pages with

navigate(‘page’,{state:{id,name})

from React Router’s useNavigate()

Hi, having a problem with my Authentication Guards. When you’re not logged in the isAuthenticated && code works, but the guarded pages load when you’re not logged in. I modified the Authentication Guard component too, but can’t remember why. Abridged version of App component:

 <Routes location={previousLocation || location}>
    <Route path="/" element={<HomePage
           ...props...
    />} />
    <Route path="/about" element={<AboutPage />} />
    <Route  path="/stories" 
            element={<Story 
            ...props...
            />} />
    <Route path="stories/:id" 
            element={<StoryDetailPage
           ...props...
            />}
            />
    <Route path="/credits" element={<Credits />} />

    <Route path="/profile/:id"
            element={<AuthenticationGuard
            component={ProfilePage}
           ...props...
/>} 
      />
    <Route path="/reviews/:id"
            element={<ReviewPage
           ...props...
            />}
    />
    <Route
      path="/edit_profile"
      element={<AuthenticationGuard 
      component={ProfileForm} />}
    />
    <Route
      path="/add_review"
      element={<AuthenticationGuard 
      component={ReviewForm} 
     ...props... />}
    />
    <Route
      path="/add_story"
      element={<AuthenticationGuard 
      component={AddStory} 
      fetchData={fetchData} 
    ...props.../>}
    />
    <Route
      path="/admin"
      element={<AuthenticationGuard 
      component={AdminPage} />}
    />
    <Route path="*" element={<NotFoundPage />} />
  </Routes>
  <Header 
  ...prop...
  />
//for modals
  {previousLocation && (
    <Routes>
      <Route
      path="/add_companion"
      element={<AuthenticationGuard 
      component={AddCompanion} 
      ...props... 
      />}
    />
      <Route
      path="/add_cast_crew"
      element={<AuthenticationGuard 
      component={AddCastCrew} 
      
   ..props...
      />}
    />
    </Routes>

and the authentication guard

import { withAuthenticationRequired } from "@auth0/auth0-react";
import React from "react";
import { PageLoader } from "../Components/Navigation/page_loader";

export const AuthenticationGuard = ({ component: Component, ...rest  }) => {
  const wrappedComponent = withAuthenticationRequired(Component, {
    onRedirecting: () => (
      <div className="page-layout">
        <PageLoader />
      </div>
    ),
  });

  return <Component {...rest}/>;
};

Hi @a.a.g.blair , welcome to the Auth0 Community!

To confirm that I understand your issue correctly, you’re not redirected to log in with Auth0 when you visit a page that requires an authenticated user (e.g., the /edit_profile route in your example). Is that correct?

From the code snippets you shared, I noticed you modified the AuthenticationGuard component to pass props down the wrapped component, which is correct. However, please notice that you’re not returning the HOC component that wraps your component with the withAuthenticationRequired HOC in the AuthenticationGuard component.

Could you try to modify your AuthenticationGuard component as follows:

import { withAuthenticationRequired } from "@auth0/auth0-react";
import React from "react";
import { PageLoader } from "../Components/Navigation/page_loader";

export const AuthenticationGuard = ({ component: Component, ...rest }) => {
  const WrappedComponent = withAuthenticationRequired(Component, {
    onRedirecting: () => (
      <div className="page-layout">
        <PageLoader />
      </div>
 ),
 });

  return <WrappedComponent {...rest} />;
};

This will ensure that when an anonymous user visits your component, they are redirected to the login page and returned to the page they were redirected to after login.

Let us know if that works for you!

Thanks for reading our developer guide!

1 Like

Oh of course, I just forgot to change that name! At least it was something simple. Thank you!

2 Likes

Hey @byron.motoche , Is there a updated version of this SDK which uses React Router V6.4 ,which uses createbrowserrouter instead of Browser router and usenavigation for example ?

From what I see, at the “Call a Protected API From React” part, you are showing the “Implicit Flow” way of connecting the backend to our SPA. This flow is actually insecure right? Could we also add a tutorial to show the secure way with authorization code flow with the PKCE extension? Sorry if I’m mistaken, I am new to auth stuff.

Hi, @rampandey , welcome to the Auth0 Community and thanks for reading our guide!

Currently, we don’t have a code sample that uses the createBrowserRouter router. We’ll work on a sample that shows how to do that. We may not be able to share the full sample too soon, but we can definitely share the code snippets within the next few weeks.

Stay tuned!

Hi @atalayozmen21 , Welcome to the Auth0 Community!.

The Auth0 React SDK under the hood uses the Authorization Code Grant Flow with PKCE. To prevent confusion, we’ll be more explicit about which Flow is used in the guide. Thanks for sharing this concern, your feedback helps us improve our developer content.

The Implicit Flow is no longer considered a best practice for requesting access tokens. However, it offers a streamlined workflow if the application only needs an ID token to perform user authentication.

Thank you once more for taking the time to use our content and share your feedback.