Implementing Auth0 Protected Routes using React Router v6...?

Hello Friends,

I’m wondering if there’s anyone who could please provide a resource on how to implement Auth0 Protected Route functionality using React Router v6?

The Auth0 React tutorial that currently exists, while very while authored, appears to be for React Router version 5 or earlier. Hence, it does not appear to work for those of us who are using v6. I have tried to make the logical updates that one would expect going from RR v5 to v6, such as using “Navigate to” instead of “Redirect,” using “element=” instead of “component=”, and changing how I wrap routes using “ProtectedRoute”, but I still cannot get things to work properly…

The errors I receive when trying to implement Protected Routes using the guide vary from
“A is only ever to be used as the child of element, never rendered directly. Please wrap your in a . protected route” to

“Error: [ProtectedRoute] is not a component. All component children of must be a or <React.Fragment>”

The errors vary depending on what change I’m attempting to implement in going from v5 to v6 using the current guide.

If anyone has a code sample or guide on how to use Auth0 with RR v6, I would be very grateful. Thanks…!

1 Like

Note- I just saw in the comments for the Auth0-React guide that the author (Dan) is planning to update the guide for React Router v6 in early 2022. Therefore, I will be patient and happily await his updates!

1 Like

Hey Rob,

In my team we recently ran into this problem and our strategy goes something like this:

const App => 
  <Routes>
    <Route path="some-path" element={<ProtectedComponent component={SomePrivateView} aProps={prop1} anotherProp={prop2} />} />
    ...more routes
  </Routes>

SomePrivateView is the component function. i.e.:

const SomePrivateView = (props) =>  <>something</>

In ProtectedComponent we let withAuthenticationRequired to the redirection if needed:

const ProtectedComponent = ({ component, ...propsForComponent}) => {
  const Cp = withAuthenticationRequired(component);
  return <Cp {...propsForComponent} />
}

For the moment, this has been enough. Hope this helps someone also looking to upgrade.

Regards,
Juan Carlos

5 Likes

Thanks Juan Carlos this works a treat!

1 Like

@jcespinoza

Apologies sir for the late response, as I got locked up in another, totally unrelated area.

Indeed - thank you for posting this. This is great, and it works…!

Just as a follow- up question… do you or anyone else happen to have any idea on how to do a redirect to another page in the case of the login attempt failing?

Auth0 appears to use a module called withAuthenticationRequired() to handle this, but it’s sort of a blackbox to me, and I can’t really find any detailed documentation on how it works. Therefore, I have no idea how to set the redirect page to something else…? The example given in the React guide is for React Router v5 only…

Thanks,

Speaking of late responses :man_facepalming:

So, when you attempt to login and fail, don’t we just get locked in that page?
One idea, if I had to navigate away from the login after a failing attempt is, I would customize Auth0’s login with my html, catch the exception and redirect somewhere else from there.

      function login(e) {
        e.preventDefault();
        var button = this;
        var username = document.getElementById("email").value;
        var password = document.getElementById("password").value;

        webAuth.login(
          {
            realm: databaseConnection,
            username: username,
            password: password,
            captcha: captcha.getValue(),
          },
          function (err) {
            if (err) {
              /* REDIRECT SOMEWHERE FROM HERE */
              window.location.replace("https://yourpage");
            }
          },
        );
      }

I know this has nothing to do with React Router so maybe I misunderstood the question, so feel free to link to those examples you mention.

Regards,
Juan Carlos

Doing the same thing in another way. In my opinion a bit clearer.

cost SomePrivateView = () => {

}

export default withAuthenticationRequired(SomePrivateView)
2 Likes

@robliou01 @jcespinoza @lolmos @holm.markus I created a code sample for React Router 6 + React 17:

I invite you to try it out, please :slight_smile: I will be gathering feedback and then building the new React Authentication guide based on it :eyes:

Right now it uses TypeScript but I’ll push a JavaScript version next week after I get some feedback :slight_smile: It’s easier to iterate using TypeScript hehe

5 Likes

Thanks for contributing to this thread and sharing it here Dan!

Thanks, Dan!

I’m currently busy trying to implement JWT access token between my Auth0 and Hasura GraphQL app setup. I see that this will all together with your tutorial. I’ll try to get to it as soon as I can, with feedback.

Thanks again,

1 Like

Take your time @robliou01 !

Dan, thanks for updating the guide!

Looks like you’ve covered the part about how to protect routes in RRv6. The only other part that I noticed would be helpful if updated is:

How do we make/update the Profile page to be conditional on whether login is successful or not?

If I have more specific questions, I will be sure to contact support or upgrade my support level…

Thanks,

Rob

On the current code sample, you need to be logged in in order to access the profile page, /profile. Is that different from your use case?

Dan,

This contains what I was looking for:

Thanks!

R

2 Likes

Thanks for sharing with the rest of community!

Excellent! @robliou01I am going to be adding a beta label to that code sample as it will be changing. I have been iterating over it and we found a “bug” in React Router v6 that causes unnecessary re-renders when one uses useNavigate().

Please refer to the basic-authentication-bug branch of the TypeScript version to see the latest integration strategy with React Router v6:

https://github.com/auth0-developer-hub/spa_react_typescript_hello-world_react-router-6/tree/basic-authentication-bug

More than likely, I will be using this approach based on BrowserRouter in both the TypeScript and JavaScript code sample. Please if you have any question, do not hesitate to let me know!

1 Like

First, thankyou and awesome work @dan-auth0 !!! I noticed that one can do Routes->Route->Routes->Route.

This got me thinking, perhaps instead “is there a way to do ProtectedRoutes plural?”

I only ask as the v5 solution was so readable and I realize you are working with v6 and have limitations. Is there a way to override Routes instead of Route and create a cleaner solutions with ProtectedRoutes and then a list of Route that are protected. This overall could be a cleaner solution. It is quite annoying that router v6 is creating this ugly hard to read mess now albeit it cleaned up other things (I guess as developers we are always posed with tradeoffs)

at any rate, thanks for all that work either way. CAVEAT: I am quite a newb in react/typescript so take everything above with the smallest grain of salt possible.

1 Like

You are welcome, Dean. I’ll share your feedback with the SDK team. I think for now, it’s a bit clearer to implement the guard component per route. I think that using the single-route component makes the process more explicit and intentional, which can mitigate errors such as leaving a route component out of that protected routes bundle by accident.

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.

Please consult our newly released React Authentication By Example: Using React Router 6 :tada: for guidance on how to integrate Auth0 with a React Router v6 application. While the guide uses React v18, the same architecture would apply to an app that uses React v17.