DEV Community

Cover image for React Mastery Series – Day 27: Authentication & Authorization in React – JWT, Protected Routes & Role-Based Access Control (RBAC)
Siva Samanthapudi
Siva Samanthapudi

Posted on

React Mastery Series – Day 27: Authentication & Authorization in React – JWT, Protected Routes & Role-Based Access Control (RBAC)

🚀 React Mastery Series – Day 27: Authentication & Authorization in React – JWT, Protected Routes & Role-Based Access Control (RBAC)

Welcome back to the React Mastery Series!

In the previous article, we explored React Testing and learned how to write reliable applications using:

  • Unit Testing
  • Integration Testing
  • End-to-End (E2E) Testing
  • React Testing Library
  • Playwright
  • Mocking APIs
  • Enterprise testing strategies

Today, we'll cover one of the most critical topics in modern web development:

Authentication & Authorization in React

Almost every enterprise application requires users to log in before accessing sensitive information.

Examples include:

  • Internet Banking
  • E-Commerce Platforms
  • Healthcare Portals
  • Insurance Applications
  • HR Management Systems
  • CRM Platforms

Building authentication correctly is essential for both security and user experience.


Authentication vs Authorization

Many developers use these terms interchangeably, but they have different meanings.

Authentication

Authentication answers the question:

Who are you?

Example:

     Username
       ↓
    Password
       ↓
Identity Verified
Enter fullscreen mode Exit fullscreen mode

Authorization

Authorization answers the question:

What are you allowed to access?

Example:

    User Logged In
         ↓
     Check Role
         ↓
      Admin?
         ↓
Yes → Admin Dashboard
No → User Dashboard
Enter fullscreen mode Exit fullscreen mode

Authentication verifies identity.

Authorization verifies permissions.


Real-World Banking Example

Imagine an online banking system.

Two users log in.

  Customer
     ↓
View Accounts
Transfer Money
Download Statements
Enter fullscreen mode Exit fullscreen mode

Bank Employee
     ↓
Approve Loans
Manage Customers
View Reports
Enter fullscreen mode Exit fullscreen mode

Both users are authenticated.

But they have different permissions.

This is authorization.


Authentication Flow

A typical login flow looks like this:

User Enters Credentials
          │
          ▼
     Backend API
          │
          ▼
   Credentials Valid?
          │
          ▼
     ┌─────────────┐
     │             │
    Yes            No
     │             │
     ▼             ▼
Generate JWT    Show Error
     │
     ▼
Store Token
     │
     ▼
Navigate to Dashboard
Enter fullscreen mode Exit fullscreen mode

What is JWT?

JWT stands for:

JSON Web Token
Enter fullscreen mode Exit fullscreen mode

It is a compact token used to securely identify authenticated users.

A JWT contains three parts:

Header.Payload.Signature
Enter fullscreen mode Exit fullscreen mode

Example:

xxxxx.yyyyy.zzzzz
Enter fullscreen mode Exit fullscreen mode

The frontend doesn't need to understand every part of the token.

It simply stores the token and sends it with future API requests.


Login Request

React sends credentials to the backend.

Example:

POST /login
Enter fullscreen mode Exit fullscreen mode

Request body:

{
  "email": "user@example.com",
  "password": "password123"
}
Enter fullscreen mode Exit fullscreen mode

Successful response:

{
  "token": "jwt-token",
  "user": {
    "id": 101,
    "name": "Siva",
    "role": "ADMIN"
  }
}
Enter fullscreen mode Exit fullscreen mode

Storing Authentication State

After login, applications usually store:

  • User information
  • Authentication status
  • Access token

Example Redux state:

interface AuthState {
  user: User | null;
  token: string | null;
  isAuthenticated: boolean;
}
Enter fullscreen mode Exit fullscreen mode

This state becomes available throughout the application.


Token Storage Options

There are multiple ways to store authentication tokens.

Storage Suitable? Notes
localStorage Sometimes Persists after browser restart but is accessible to JavaScript.
sessionStorage Sometimes Cleared when the browser tab closes.
HTTP-Only Cookies Recommended More resistant to JavaScript-based attacks because scripts cannot access them.

Many enterprise applications prefer HTTP-Only Cookies because they offer stronger protection against certain attack vectors.


Attaching Tokens to API Requests

Authenticated requests typically include the token in the Authorization header.

Example:

GET /accounts

Authorization: Bearer jwt-token
Enter fullscreen mode Exit fullscreen mode

Using Axios:

api.interceptors.request.use((config) => {
  const token = localStorage.getItem("token");

  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }

  return config;
});
Enter fullscreen mode Exit fullscreen mode

This automatically attaches the token to every request.


Protected Routes

Some pages should only be accessible to authenticated users.

Examples:

/

Login

About
Enter fullscreen mode Exit fullscreen mode

Public routes.


/dashboard

/accounts

/profile

/settings
Enter fullscreen mode Exit fullscreen mode

Protected routes.


Creating a Protected Route

Example:

import { Navigate } from "react-router-dom";

type ProtectedRouteProps = {
  children: React.ReactNode;
  isAuthenticated: boolean;
};

function ProtectedRoute({
  children,
  isAuthenticated,
}: ProtectedRouteProps) {
  if (!isAuthenticated) {
    return <Navigate to="/login" replace />;
  }

  return <>{children}</>;
}

export default ProtectedRoute;
Enter fullscreen mode Exit fullscreen mode

Usage:

<Rout path="/dashboard" element={
    <ProtectedRouteisAuthenticated={isAuthenticated}>
      <Dashboard />
    </ProtectedRoute>
  }
/>
Enter fullscreen mode Exit fullscreen mode

If the user isn't logged in, they're redirected to the login page.


Role-Based Access Control (RBAC)

Authentication answers:

"Who is the user?"

RBAC answers:

"What can this user do?"

Example:

ADMIN
↓
Dashboard
Users
Reports
Settings
Enter fullscreen mode Exit fullscreen mode

CUSTOMER
   ↓
Dashboard
Accounts
Transactions
Enter fullscreen mode Exit fullscreen mode

Different roles see different features.


Role-Based Rendering

Example:

{
  user.role === "ADMIN" && (<AdminPanel />);
}
Enter fullscreen mode Exit fullscreen mode

The component is rendered only for administrators.

Remember:

Frontend checks improve the user experience, but the backend must always enforce authorization.


Logout Flow

Logging out should:

  • Clear authentication state
  • Remove stored tokens
  • Redirect to the login page

Example:

function logout() {
  localStorage.removeItem("token");
  dispatch(clearUser());
  navigate("/login");
}
Enter fullscreen mode Exit fullscreen mode

After logout:

User Clicks Logout
        │
        ▼
   Remove Token
        │
        ▼
Clear Redux State
        │
        ▼
Navigate to Login
Enter fullscreen mode Exit fullscreen mode

Refresh Tokens

Access tokens usually have a short expiration time.

Instead of forcing users to log in repeatedly:

Access Token Expires
        │
        ▼
 Refresh Token
        │
        ▼
New Access Token
        │
        ▼
 Continue Session
Enter fullscreen mode Exit fullscreen mode

This improves both security and user experience.


Enterprise Authentication Architecture

   React App
       │
       ▼
  Login API
       │
       ▼
  JWT Issued
       │
       ▼
Redux/Auth Context
       │
       ▼
 Axios Interceptor
       │
       ▼
 Protected APIs
Enter fullscreen mode Exit fullscreen mode

Each layer has a specific responsibility.


Folder Structure

A scalable authentication module:

src
├── features
│   └── auth
│       ├── components
│       ├── hooks
│       ├── pages
│       ├── services
│       ├── authSlice.ts
│       └── types.ts
├── routes
│   └── ProtectedRoute.tsx
├── api
    └── axios.ts
Enter fullscreen mode Exit fullscreen mode

This keeps authentication logic organized and maintainable.


Common Mistakes

1. Storing Sensitive Data in the Frontend

Avoid storing confidential information such as passwords or secrets in React applications.

Only store what's necessary for the client.


2. Relying Only on Frontend Authorization

Hiding buttons isn't enough.

The backend must always verify permissions before returning sensitive data or performing privileged actions.


3. Forgetting Token Expiration

Applications should gracefully handle expired tokens by:

  • Refreshing them (when applicable)
  • Redirecting users to log in again if refresh fails

4. Not Clearing Authentication State on Logout

Always remove tokens and reset application state when users sign out.


Best Practices

  • Use HTTPS for all authenticated communication.
  • Protect sensitive routes.
  • Handle expired tokens gracefully.
  • Keep authentication logic centralized.
  • Separate authentication from authorization.
  • Validate permissions on the backend.
  • Store only the minimum required user information in the frontend.

Key Takeaways

Today, we learned:

✅ Authentication verifies user identity.
✅ Authorization determines what users are allowed to access.
✅ JWT is commonly used for stateless authentication.
✅ Protected routes prevent unauthorized access to pages.
✅ RBAC enables role-specific experiences.
✅ Refresh tokens improve both security and usability.
✅ Backend authorization is mandatory, even if the frontend hides restricted features.


Coming Next 🚀

In Day 28, we will explore:

React Design Patterns – Compound Components, Render Props, Higher-Order Components & Custom Hooks

We will learn:

  • Why design patterns matter
  • Compound Components
  • Render Props
  • Higher-Order Components (HOCs)
  • Provider Pattern
  • Custom Hook Pattern
  • Composition over inheritance
  • Enterprise React design principles

These patterns will help you build reusable, maintainable, and scalable React applications like those used in large engineering teams.

Happy Coding! 🚀

React #ReactJS #Authentication #Authorization #JWT #RBAC #FrontendDevelopment #TypeScript #WebDevelopment #SoftwareArchitecture

Top comments (0)