Skip to main content

Overview

The AuthGuard component is a higher-order component that wraps protected routes to ensure only authenticated users can access them. It integrates with Auth0 to check authentication status and handles loading, unauthenticated, and error states. Source: src/components/AuthGuard.tsx

Key Features

  • Checks user authentication status before rendering protected content
  • Displays loading spinner during authentication check
  • Redirects unauthenticated users to login page
  • Handles authentication errors gracefully
  • Seamlessly renders protected component when authenticated

Props

The component accepts a single prop defined by the AuthGuardProps interface:
component
React.ReactElement
required
The protected component to render when the user is authenticated.

TypeScript Interface

interface AuthGuardProps {
    component: React.ReactElement;
}

Authentication States

AuthGuard handles four distinct authentication states:

1. Loading State

While Auth0 is checking authentication status, a centered loading spinner is displayed:
if (isLoading) {
    return (
        <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
            <CircularProgress />
        </Box>
    );
}

2. Unauthenticated State

If the user is not authenticated, they are redirected to the Login component:
if (!isAuthenticated) {
    console.log('User is not authenticated, redirecting to login');
    return <Login />;
}

3. Error State

If an authentication error occurs, an error message is displayed:
if (error) {
    return <div>Oops... {error.message}</div>;
}

4. Authenticated State

When successfully authenticated, the protected component is rendered:
return <>{component}</>;

Usage Examples

Basic Usage with React Router

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import AuthGuard from './components/AuthGuard';
import Dashboard from './pages/Dashboard';
import Settings from './pages/Settings';

function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/dashboard" element={
                    <AuthGuard component={<Dashboard />} />
                } />
                <Route path="/settings" element={
                    <AuthGuard component={<Settings />} />
                } />
            </Routes>
        </BrowserRouter>
    );
}

Protecting Multiple Routes

import AuthGuard from './components/AuthGuard';
import MasterLayout from './components/MasterLayout';

function App() {
    return (
        <Routes>
            <Route path="/" element={
                <AuthGuard component={<MasterLayout />} />
            }>
                {/* Nested routes are automatically protected */}
                <Route path="dashboard" element={<Dashboard />} />
                <Route path="api-tests" element={<ApiTesting />} />
            </Route>
        </Routes>
    );
}

Custom Protected Page

import AuthGuard from './components/AuthGuard';
import MyProtectedPage from './pages/MyProtectedPage';

function ProtectedRoute() {
    return (
        <AuthGuard 
            component={
                <MyProtectedPage 
                    title="Protected Content"
                    data={myData}
                />
            } 
        />
    );
}

Integration with Auth0

AuthGuard uses the useAuth0 hook to access authentication state:
const { isAuthenticated, isLoading, error } = useAuth0();

Required Setup

Ensure your app is wrapped with the Auth0 provider:
import { Auth0Provider } from '@auth0/auth0-react';

function App() {
    return (
        <Auth0Provider
            domain="your-domain.auth0.com"
            clientId="your-client-id"
            authorizationParams={{
                redirect_uri: window.location.origin
            }}
        >
            <YourAppRoutes />
        </Auth0Provider>
    );
}

Material-UI Components

AuthGuard uses the following Material-UI components:
  • Box: Container for layout and styling
  • CircularProgress: Loading spinner during authentication check

Complete Source Code

import React from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import { CircularProgress, Box } from '@mui/material';
import Login from './Login';

interface AuthGuardProps {
    component: React.ReactElement;
}

const AuthGuard: React.FC<AuthGuardProps> = ({ 
    component
}) => {
    const { isAuthenticated, isLoading, error } = useAuth0();

    if (isLoading) {
        return (
            <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
                <CircularProgress />
            </Box>
        );
    }

    if (!isAuthenticated) {
        console.log('User is not authenticated, redirecting to login');
        return <Login />;
    }

    if (error) {
        return <div>Oops... {error.message}</div>;
    }   

    return <>{component}</>;
};

export default AuthGuard;

Best Practices

  1. Wrap at Route Level: Apply AuthGuard at the route level rather than individual components
  2. Nested Protection: Protect parent routes to automatically protect all child routes
  3. Error Handling: Consider customizing the error UI for better user experience
  4. Loading State: The default loading spinner works well, but can be customized if needed
  5. Logging: Keep authentication logs for debugging purposes (already included)

Build docs developers (and LLMs) love