HTTP
401 - Unauthorized
Hitting a 401 Unauthorized means the server rejected your request because authentication is required—missing Authorization header, expired JWT token, or invalid credentials. This client-side error (4xx) occurs when the server can't verify your identity. Most common in API calls where Bearer tokens are missing or expired, but also appears when session cookies expire or login credentials are incorrect.
#Common Causes
- →Frontend: Missing Authorization header in fetch/axios requests. Token expired but not refreshed. Token stored incorrectly (localStorage vs sessionStorage). CORS preflight fails before auth header is sent.
- →Backend: JWT token validation middleware rejects expired or malformed tokens. Session middleware can't find session cookie. Password hashing comparison fails. Token blacklist/revocation check fails.
- →Infrastructure: Reverse proxy strips Authorization headers. Load balancer session affinity breaks. CDN caching protected routes. Nginx auth_request module fails upstream check.
✓Solutions
- 1Step 1: Diagnose - Open DevTools Network tab, check Request Headers for Authorization: Bearer <token>. Verify token exists and isn't expired (decode JWT at jwt.io). Check if token is sent on preflight OPTIONS request.
- 2Step 2: Diagnose - Check server logs for authentication failures. Look for "Token expired", "Invalid signature", or "Session not found" errors. Review middleware execution order.
- 3Step 3: Fix - Client-side: Implement token refresh logic—intercept 401 responses, call /refresh endpoint, retry original request. Store tokens securely (httpOnly cookies preferred over localStorage).
- 4Step 4: Fix - Server-side: Add proper JWT validation middleware. Check token expiration (exp claim), verify signature, validate issuer (iss) and audience (aud). Implement token refresh endpoint with rotation.
- 5Step 5: Fix - Infrastructure: Ensure Nginx/Apache passes Authorization headers to backend (proxy_set_header Authorization $http_authorization). Disable caching for protected routes. Verify session affinity in load balancer.
</>Code Examples
Fetch API: Token Refresh on 401
1// Client-side: Handle 401 with automatic token refresh
2async function fetchWithAuth(url, options = {}) {
3 let token = localStorage.getItem('authToken');
4
5 const response = await fetch(url, {
6 ...options,
7 headers: {
8 'Authorization': `Bearer ${token}`,
9 'Content-Type': 'application/json',
10 ...options.headers,
11 },
12 });
13
14 if (response.status === 401) {
15 // Token expired, refresh it
16 const refreshResponse = await fetch('/api/auth/refresh', {
17 method: 'POST',
18 credentials: 'include', // Include httpOnly refresh token cookie
19 });
20
21 if (refreshResponse.ok) {
22 const { accessToken } = await refreshResponse.json();
23 localStorage.setItem('authToken', accessToken);
24
25 // Retry original request with new token
26 return fetch(url, {
27 ...options,
28 headers: {
29 'Authorization': `Bearer ${accessToken}`,
30 'Content-Type': 'application/json',
31 ...options.headers,
32 },
33 });
34 } else {
35 // Refresh failed, redirect to login
36 window.location.href = '/login';
37 throw new Error('Authentication failed');
38 }
39 }
40
41 return response;
42}Express.js: JWT Authentication Middleware
1// Server-side: JWT validation middleware
2const jwt = require('jsonwebtoken');
3const express = require('express');
4const app = express();
5
6const authenticateToken = (req, res, next) => {
7 const authHeader = req.headers['authorization'];
8 const token = authHeader && authHeader.split(' ')[1]; // Bearer <token>
9
10 if (!token) {
11 return res.status(401).json({ error: 'Access token required' });
12 }
13
14 jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
15 if (err) {
16 if (err.name === 'TokenExpiredError') {
17 return res.status(401).json({ error: 'Token expired' });
18 }
19 return res.status(401).json({ error: 'Invalid token' });
20 }
21
22 req.user = user;
23 next();
24 });
25};
26
27// Protected route
28app.get('/api/protected', authenticateToken, (req, res) => {
29 res.json({ message: 'Protected data', user: req.user });
30});Nginx: Pass Authorization Headers
1# Nginx: Ensure Authorization headers reach backend
2server {
3 listen 80;
4 server_name api.example.com;
5
6 location /api/ {
7 proxy_pass http://backend;
8
9 # Pass authorization header to backend
10 proxy_set_header Authorization $http_authorization;
11 proxy_set_header Host $host;
12 proxy_set_header X-Real-IP $remote_addr;
13
14 # Don't cache authenticated requests
15 proxy_cache_bypass $http_authorization;
16 add_header Cache-Control "no-store, no-cache";
17 }
18}↗Related Errors
Provider Information
This error code is specific to HTTP services. For more information, refer to the official HTTP documentation.