Introduction
Authentication is the foundation of secure web applications. This tutorial walks through implementing JWT-based authentication in a React application with proper token handling, protected routes, and refresh token patterns.
Prerequisites
- Node.js 18+
- React 19 with TypeScript
- Basic understanding of REST APIs
Step 1: Create the Auth Context
import { createContext, useContext, useState, useCallback } from 'react';
type AuthContextType = {
token: string | null;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
};
const AuthContext = createContext<AuthContextType | null>(null);
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [token, setToken] = useState<string | null>(null);
const login = useCallback(async (email: string, password: string) => {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
const data = await res.json();
setToken(data.token);
}, []);
const logout = useCallback(() => setToken(null), []);
return (
<AuthContext.Provider value={{ token, login, logout }}>
{children}
</AuthContext.Provider>
);
}
export const useAuth = () => {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
};
Step 2: Protected Routes
Wrap routes that require authentication:
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { token } = useAuth();
if (!token) return <Navigate to="/login" />;
return <>{children}</>;
}
Step 3: API Interceptor
Attach the JWT to all API requests:
const api = axios.create({ baseURL: '/api' });
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
Security Best Practices
- Store tokens in httpOnly cookies when possible
- Implement refresh token rotation
- Set short access token expiry (15 minutes)
- Use HTTPS in production
- Validate tokens server-side on every request
Conclusion
JWT authentication in React requires careful token management. For production applications, consider OAuth 2.0 with PKCE for third-party login flows.

