React Authentication By Example: React Router 6

This React guide will help you learn how to secure a React application using token-based authentication. You’ll learn how to use React along with the Auth0 React SDK and React Router 6 to implement user authentication, route protection, and access protected data from external APIs.

2 Likes

Is there a working sample (may be a sandbox) where we can play with it ? sorry if that makes no sense :expressionless:

Hello, Kishore. Welcome to the Auth0 Community.

We expect developers to run the code sample from the guide on their own machines so that they can easily use their own Auth0 Configuration variables. Devs can technically run the repo on a cloud IDE like Stackblitz and CodeSandbox but they will need to do some tweaks in order for Auth0 to communicate properly with those environments.

Since the project also has an API component, that part of the demo may not work on those IDEs. As such, it’s better to run the demo locally :slight_smile:

1 Like

I think

<Route
        path="/profile"
        element={<AuthenticationGuard component={<ProfilePage />} />}
/>

should be

<Route
        path="/profile"
        element={<AuthenticationGuard component={ProfilePage} />}
/>
2 Likes

Thanks Dan for the response, it makes sense … sure will try it in my local machine :handshake:

1 Like

Hey all,

I’m currently working through the React Authentication By Example: Using React Router 6 guide for my self-hosted site, which is running React v18.2.0, React Router v6.3.0, & React Scripts v5.0.1.

I’m at the “Add Route Guards to React” section & created src/pages/profile-page.js per docs to test things out with the <AuthenticationGuard/> element, prior to rolling out for my production pages. My example.com/profile page redirects to my Auth0 login as expected, for auth.example.com, however after signing in this returns a blank screen & the following error in my browser console:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <ProfilePage />. Did you accidentally export a JSX literal instead of a component?

Anyone have any idea what’s going on here?

I have a pastebin for my index.js, App.js, auth0-provider-with-navigate.js, authentication-guard.js, profile-page.js & callback-page.js, yet will share what I have for App.js below.

App.js:

import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import { Auth0ProviderWithNavigate } from "./auth0-provider-with-navigate";
import { AuthenticationGuard } from "./components/authentication-guard";
import { ProfilePage } from "./pages/profile-page";
import { CallbackPage } from "./pages/callback-page";

function App() {
  return (
  <BrowserRouter>
    <Auth0ProviderWithNavigate>
      <Routes>
        <Route path='/profile' element={<AuthenticationGuard component={<ProfilePage/>} />} />
        <Route path="/callback" element={<CallbackPage />} />
      </Routes>
    </Auth0ProviderWithNavigate>
  </BrowserRouter>
  );
}
export default App;

Thanks,
Nick

1 Like

I had the same error and after further investigation, I went back to the sample repository and found out that instead of:

<AuthenticationGuard component={<ProfilePage />} />

like in the guide, the sample repository actually uses the one below which works for me.

<AuthenticationGuard component={ProfilePage} />

https://github.com/auth0-developer-hub/spa_react_javascript_hello-world_react-router-6/blob/main/src/app.js

1 Like

Thanks.

That worked for my test Profile page, yet doesn’t for components with props (I’d never before seen a component nested within an element under Routes).

I guess now the question is how to transform the below:
<Route path='/data' element={<DataPage data1={{var1, var2, var3}} data2={var4} data3={var5}/>} />

To something with props under React Router 6:
<Route path='/data' element={<AuthenticationGuard component={DataPage}...

How would I pass <AuthenticationGuard/> in Routes against components with props? Only errors are coming up from my end.

@dan-auth0 , @bmotoche are you able to help on that front? Thank you!

2 Likes

Thanks @konrad.sopala.

For reference: I’m currently passing my components through Routes the following way:

<Route path='/:siteID/history/*' element={<History data={{siteID, stateID, cityID}} customerID={''}/>} />
<Route path='/:siteID/history/:page' element={<History data={{siteID, stateID, cityID}} customerID={''}/>} />

I’d never before seen examples of nesting Route elements with components while properly passing props in React 18 / Router 6, especially with <AuthenticationGuard>.

My question here is how are props passed when changing “element={<History” to “element={History}”?

Thanks, @konrad.sopala, for connecting the dots.
Hi @ymonye, what @bren.codes and @nikyo suggested is correct. We should pass the ProfilePage as follows:

<AuthenticationGuard component={ProfilePage} />

We fixed this in the guide. Thanks for pointing it out.

1 Like

Thanks, but how are props passed after changing component={<DataPage to component={DataPage

The above breaks the code

@bmotoche also mentioning a part that needs to be changed in the article in order to make it work.

Instead of:

<Route
    path="/profile"
    element={<AuthenticationGuard component={<ProfilePage />} />}
  />

it should be:

 <Route
    path="/profile"
    element={<AuthenticationGuard component={ProfilePage} />}
  />
1 Like

Hey team,

How do I implement <AuthenticationGuard> into elements with props? Following your guide, it’s not very clear.

Prior to AuthenticationGuard, my routes (under React Router 6) are setup as:

<Route path='/:siteID/history/*' element={<History data={{siteID, stateID, cityID}} customerID={''}/>} />

This History.js component is setup as:

import {useEffect, useState} from 'react';
import {useLocation, useParams} from 'react-router-dom'
import '../App.css';

function History ({data, customerID}){
    //Main code...
    return(
       //Return code...
    )
}

export default History;

After following through the guide, this Route was revised to:

<Route path='/:siteID/history/*' element={<AuthenticationGuard component={History} data={{siteID, stateID, cityID}} customerID={''}/>} />

The main problem is props are not being passed to the <History> component. I’d tried various combinations with the braces, as well as Google search for examples of passing props to components nested with elements, with zero luck.

The below fails as well:

<Route path='/:siteID/history/*' element={<AuthenticationGuard component={History data={{siteID, stateID, cityID}} customerID={''}}/>} />

How are props supposed to be passed within <AuthenticationGuard> gated Routes?

Thanks

1 Like

Hello @ymonye, we found a solution that can help you with the use case of passing props to a component that you need to protect with the <AuthenticationGuard>.

  1. You can update the src/components/authentication-guard.js to the following content:
import { withAuthenticationRequired } from "@auth0/auth0-react";
import React from "react";
import { PageLoader } from "./page-loader";

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

  return <Component {...props} />;
};
  1. Since the AuthenticationGuard expects a ComponentType, like ProtectedPage, rather than a React Element, like <ProtectedPage />, you should pass the props for your component to the AuthenticationGuard component as follows in the src/app.js file:
<Route path="/:siteID/history/*" element={<AuthenticationGuard component={History} data={{siteID, stateID, cityID}} customerID={''} />} />

While passing props to a guarded component is not common as they are usually top-level components, we can include an aside in the Developer Guide if you find this solution suitable. Please let us know if this works well for you.

Thank you for helping us make this guide stronger.

2 Likes




I don’t know why I am getting this error

1 Like

hi can anyone help please

1 Like

Tagging you @byron.motoche for visibility

1 Like

Hi @dev_bas, Welcome to the Auth0 Community.

The error you’re getting is related to how you’re passing the Login component as the element prop to the <Route> component. With React Router v6, you should use regular elements instead of components (or element types) for rendering. You can read more information about its benefits in the migration guide from React Router v5 to React Router v6.

To fix the issue, do the following in your App component:

function App() {
  return (
    <main>
      <Routes>
        <Route path="/" element={<Login />} />
        <Route
          path="/profile"
          element={<AuthenticationGuard component={Dashboard} />}
        />
      </Routes>
    </main>
  );
}

Please let us know if this works well for you.

1 Like