Currently, users can access the profile route of our app whether or not they're logged in. We can fix this using a higher order component in React. Higher order components are just functions that receive a component and return a component. In our case, we will wrap the Route component provided by react-router-dom. We're going to check if the user is authenticated, and if not, redirect the user to Auth0 to log in.

Create a new file under src/components called PrivateRoute.js. The finished code will look like this:

// src/components/PrivateRoute.js
import React, { useEffect } from 'react';
import { Route } from 'react-router-dom';
import { useAuth0 } from '../react-auth0-spa';

const PrivateRoute = ({ component: Component, path, ...rest }) => {
  const { loading, isAuthenticated, loginWithRedirect } = useAuth0();

  useEffect(() => {
    if (loading || isAuthenticated) {
      return;
    }
    const fn = async () => {
      await loginWithRedirect({
        appState: { targetUrl: path }
      });
    };
    fn();
  }, [loading, isAuthenticated, loginWithRedirect, path]);

  const render = props =>
    isAuthenticated === true ? <Component {...props} /> : null;

  return <Route path={path} render={render} {...rest} />;
};

export default PrivateRoute;

Finally, update App.js to use PrivateRoute instead of Route for the profile route. Don't forget to import the PrivateRoute component!

The finished App.js will look like this:

// src/App.js
import React from 'react';
import NavBar from './components/NavBar';
import { useAuth0 } from './react-auth0-spa';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Profile from './components/Profile';
import PrivateRoute from './components/PrivateRoute';

function App() {
  const { loading } = useAuth0();

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div className="App">
      <BrowserRouter>
        <header>
          <NavBar />
        </header>
        <Switch>
          <Route path="/" exact />
          <PrivateRoute path="/profile" component={Profile} />
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Everything should now work as expected. Run npm start, head to localhost:3000, and log in. Click between the home and profile routes, then log out. Try to navigate to localhost:3000/profile. You should be redirected to Auth0.

Great work! Let's recap and wrap up this tutorial in the final video.