Paramclasses Academy - Blog

Tutorials Details

←
Post 21 of 29
→

WHat is Authentication and Protected Routes in React Applications

WHat is Authentication and Protected Routes in React Applications

October 30, 2026

1. Introduction

Authentication is an important part of modern web applications. It helps applications identify users and control access to specific features and pages.

For example, when a user opens an e-commerce website, they may be able to browse products without logging in. However, accessing their account, viewing private orders, or updating profile information may require authentication.

React provides tools such as state, context, and routing libraries that help developers implement authentication flows in the frontend.

In this tutorial, we will learn how to create login and registration interfaces, manage authentication state, and protect routes from unauthenticated users.

Main Goal: Understand authentication concepts and build a React application with login functionality and protected routes.

2. Learning Objectives

After completing this tutorial, you will understand:

  1. What authentication means.

  2. What authorization means.

  3. The difference between authentication and authorization.

  4. How login and registration work.

  5. How to manage authentication state in React.

  6. How to use the Context API for authentication.

  7. What protected routes are.

  8. How to redirect unauthenticated users to a login page.

  9. How logout functionality works.

  10. Important authentication security practices.

3. Core Concepts and Explanation

3.1 What Is Authentication?

Authentication is the process of verifying the identity of a user.

It helps an application determine whether a user is who they claim to be.

For example, when a user enters an email address and password, the application sends the credentials to an authentication server.

The server verifies the credentials and returns an appropriate response.

Example:

A user enters:

Email: user@example.com
Password: ********

The server checks whether the provided credentials are valid.

If they are valid, the server establishes an authenticated session or returns an authentication token.

3.2 What Is Authorization?

Authorization is the process of determining what an authenticated user is allowed to access or perform.

For example:

  • An Admin can manage users.

  • A Customer can view their own orders.

  • A Guest can view public pages.

Easy Definition:

  • Authentication = Who are you?

  • Authorization = What are you allowed to do?

3.3 Authentication vs Authorization

Authentication Authorization
Verifies user identity Checks user permissions
Happens during login Happens when accessing protected resources
Uses credentials or identity proof Uses roles and permissions
Answers who the user is Answers what the user can do

3.4 What Is a Login System?

A login system allows an existing user to access an application using their registered credentials.

A typical login process:

  1. User opens the login page.

  2. User enters email and password.

  3. React sends credentials to the backend.

  4. Backend verifies the credentials.

  5. Backend creates a session or returns an authentication token.

  6. React updates the authentication state.

  7. User can access authorized pages.

3.5 What Is a Registration System?

A registration system allows a new user to create an account.

A typical registration form may contain:

  • Full Name

  • Email Address

  • Password

  • Confirm Password

The application sends this information to the backend, where the server validates the data and securely stores the user's account information.

Passwords must never be stored as plain text. They should be securely hashed on the backend.

3.6 What Is Authentication State?

Authentication state represents whether a user is currently authenticated.

In React, we can manage authentication state using:

  • useState

  • useContext

  • useReducer

For example:

const [isAuthenticated, setIsAuthenticated] = useState(false);

Here:

  • true means the frontend considers the user authenticated.

  • false means the frontend considers the user unauthenticated.

In a real application, this state should be based on a validated server session or authentication response.

3.7 What Is a Protected Route?

A protected route is a route that only authenticated or authorized users can access.

For example:

Page Access
Home Public
About Public
Login Public
Register Public
Dashboard Authenticated users
Profile Authenticated users
Admin Panel Authorized administrators

If an unauthenticated user tries to open the Dashboard, the application can redirect them to the Login page.

3.8 What Is a JWT?

JWT stands for JSON Web Token.

It is a compact token format commonly used to represent claims between a client and a server.

A JWT has three main parts:

  1. Header

  2. Payload

  3. Signature

The parts are separated by dots.

A JWT may contain information such as a user identifier, role, and expiration time.

Important: A JWT payload is encoded, not encrypted by default. Do not store passwords or sensitive secrets inside it.

3.9 What Is Logout?

Logout is the process of ending an authenticated user's session.

A logout operation may:

  • Invalidate the server session.

  • Clear an authentication cookie.

  • Revoke or expire a refresh token.

  • Update the frontend authentication state.

  • Redirect the user to the login page.

Simply changing a React state variable is not sufficient to securely end a real server session.

4. Practical Code Examples

Example 1: Creating a Basic Login Component

import { useState } from "react";

function Login() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  function handleLogin(e) {
    e.preventDefault();

    console.log("Email:", email);
    console.log("Password:", password);
  }

  return (
    <div>
      <h2>Login</h2>

      <form onSubmit={handleLogin}>
        <input
          type="email"
          placeholder="Enter Email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />

        <br /><br />

        <input
          type="password"
          placeholder="Enter Password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
        />

        <br /><br />

        <button type="submit">
          Login
        </button>
      </form>
    </div>
  );
}

export default Login;

Explanation:

  • useState stores the email and password input values.

  • onChange updates the input state.

  • onSubmit handles form submission.

  • preventDefault prevents the browser's default form submission.

  • The example logs form values for demonstration only.

This is a frontend form, not a secure authentication system. Never log real passwords or treat a successful form submission as proof of identity.

Example 2: Creating a Basic Registration Component

import { useState } from "react";

function Register() {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  function handleRegister(e) {
    e.preventDefault();

    console.log("Name:", name);
    console.log("Email:", email);

    // Send registration data to the backend.
  }

  return (
    <div>
      <h2>Register</h2>

      <form onSubmit={handleRegister}>
        <input
          type="text"
          placeholder="Enter Name"
          value={name}
          onChange={(e) => setName(e.target.value)}
          required
        />

        <br /><br />

        <input
          type="email"
          placeholder="Enter Email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />

        <br /><br />

        <input
          type="password"
          placeholder="Enter Password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
        />

        <br /><br />

        <button type="submit">
          Register
        </button>
      </form>
    </div>
  );
}

export default Register;

In a real application, send registration data to a backend over HTTPS. The backend must validate the input and hash the password securely.

Example 3: Creating Authentication Context

Context API allows multiple components to access shared authentication state without passing props through every component.

Create a file named AuthContext.jsx.

import { createContext, useContext, useState } from "react";

const AuthContext = createContext(null);

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  function login(userData) {
    setUser(userData);
  }

  function logout() {
    setUser(null);
  }

  const value = {
    user,
    isAuthenticated: Boolean(user),
    login,
    logout
  };

  return (
    <AuthContext.Provider value={value}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  return useContext(AuthContext);
}

Explanation:

  • createContext creates an authentication context.

  • AuthProvider shares authentication data with child components.

  • user stores the current user information.

  • login updates the user state.

  • logout clears the user state.

  • useAuth provides convenient access to the context.

This is a frontend state-management example. A production login function must first communicate with the backend and validate the authentication response.

Example 4: Providing Authentication Context to the Application

Open main.jsx.

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { AuthProvider } from "./AuthContext";

ReactDOM.createRoot(
  document.getElementById("root")
).render(
  <React.StrictMode>
    <AuthProvider>
      <App />
    </AuthProvider>
  </React.StrictMode>
);

Now all components inside App can access the authentication context.

Example 5: Creating a Protected Route

First install React Router if it is not already installed:

npm install react-router

Create ProtectedRoute.jsx.

import { Navigate, Outlet } from "react-router";
import { useAuth } from "./AuthContext";

function ProtectedRoute() {
  const { isAuthenticated } = useAuth();

  if (!isAuthenticated) {
    return <Navigate to="/login" replace />;
  }

  return <Outlet />;
}

export default ProtectedRoute;

Explanation:

  • useAuth accesses the authentication state.

  • Navigate redirects unauthenticated users.

  • replace prevents the denied route from remaining as a new history entry.

  • Outlet renders the protected child route when access is allowed.

Example 6: Setting Up Public and Protected Routes

Create App.jsx.

import {
  BrowserRouter,
  Routes,
  Route
} from "react-router";

import Login from "./Login";
import Register from "./Register";
import Dashboard from "./Dashboard";
import Home from "./Home";
import ProtectedRoute from "./ProtectedRoute";

function App() {
  return (
    <BrowserRouter>
      <Routes>

        <Route path="/" element={<Home />} />

        <Route path="/login" element={<Login />} />

        <Route path="/register" element={<Register />} />

        <Route element={<ProtectedRoute />}>
          <Route
            path="/dashboard"
            element={<Dashboard />}
          />
        </Route>

      </Routes>
    </BrowserRouter>
  );
}

export default App;

Explanation:

  • Home is a public route.

  • Login is a public route.

  • Register is a public route.

  • Dashboard is inside ProtectedRoute.

  • Unauthenticated users are redirected to Login.

Example 7: Creating a Dashboard Component

import { useAuth } from "./AuthContext";
import { useNavigate } from "react-router";

function Dashboard() {
  const { user, logout } = useAuth();
  const navigate = useNavigate();

  function handleLogout() {
    logout();
    navigate("/login", { replace: true });
  }

  return (
    <div>
      <h1>Dashboard</h1>

      <p>
        Welcome, {user?.name}
      </p>

      <button onClick={handleLogout}>
        Logout
      </button>
    </div>
  );
}

export default Dashboard;

This example demonstrates frontend logout state management. A real logout handler must also call the backend logout endpoint or otherwise invalidate the server-side session.

5. Real-World Applications

Authentication and protected routes are used in many applications.

E-commerce Websites

  • Customer Login

  • Customer Registration

  • My Account

  • Order History

  • Protected Checkout Information

Admin Dashboards

  • Admin Login

  • Protected Admin Panel

  • User Management

  • Role-Based Permissions

  • Dashboard Access

Learning Management Systems

  • Student Login

  • Instructor Login

  • Course Dashboard

  • Protected Learning Content

  • Student Progress

Banking Applications

  • Secure User Login

  • Account Dashboard

  • Transaction History

  • Role-Based Access

  • Session Management

6. Common Mistakes and Best Practices

Common Mistakes

  1. Storing passwords in localStorage.

  2. Treating frontend authentication state as proof of identity.

  3. Protecting routes only in React without backend authorization.

  4. Forgetting to handle expired sessions.

  5. Not validating login and registration data on the server.

  6. Storing sensitive information in a JWT payload.

  7. Forgetting to implement logout on the server.

  8. Allowing users to access admin APIs by changing frontend state.

Best Practices

  1. Always validate credentials on the backend.

  2. Use HTTPS for authentication requests.

  3. Store passwords using secure password hashing on the server.

  4. Prefer secure, HttpOnly, SameSite cookies for session or token handling where appropriate.

  5. Validate authorization on every protected backend request.

  6. Use role-based access control when different users have different permissions.

  7. Handle expired sessions gracefully.

  8. Implement proper logout and session invalidation.

  9. Never expose private API keys or secrets in React frontend code.

  10. Keep frontend authentication state synchronized with the server.

  11. Apply CSRF protection when using cookie-based authentication where required.

  12. Use appropriate rate limiting and login protections on the backend.

Important Security Note:

React protected routes control frontend navigation and user experience. They do not secure backend data by themselves. Every sensitive API endpoint must independently verify the user's identity and permissions.

7. Practice Exercises

Exercise 1: Create a Login page using email and password fields.

Exercise 2: Create a Registration page with name, email, password, and confirm password.

Exercise 3: Create an AuthContext using createContext and useContext.

Exercise 4: Create a ProtectedRoute component using React Router.

Exercise 5: Create a Dashboard page that only authenticated users can access.

Exercise 6: Add a Logout button that clears authentication state and redirects to Login.

Exercise 7: Create separate routes for Admin and Customer users.

Exercise 8: Connect the React login and registration forms to a backend authentication API.

8. Key Takeaways and Conclusion

In this tutorial, we learned how authentication and protected routes work in React applications.

Key takeaways:

  • Authentication verifies the identity of a user.

  • Authorization determines what a user can access.

  • Login allows registered users to access their accounts.

  • Registration allows new users to create accounts.

  • Context API helps manage shared authentication state.

  • Protected routes control access to frontend pages.

  • JWT is a commonly used token format.

  • Logout ends an authenticated session.

  • Backend authorization is essential for real application security.

Final Conclusion:

Authentication is an essential feature of professional React applications. By combining React Context API, React Router, and a secure backend authentication system, developers can build applications with organized login flows and controlled access.

Remember: Frontend route protection improves navigation and user experience, but actual security must always be enforced by the backend.

←
Post 21 of 29
→