How to Send Auth Token using JSON Web Token (JWT)🔐🔑
If you're building a React app that talks to a protected backend API, you'll eventually need to
prove who the user is on every request. That's exactly what a JWT (JSON Web Token)
is for. In this beginner-friendly React JS tutorial, we'll learn how to store a JWT after login
and send it as an Authorization header with every API request — the standard way modern
React apps handle authentication.
In this tutorial, we will learn:
What a JSON Web Token (JWT) is and how auth tokens work
Storing the JWT safely after a successful login
Sending the token using the Authorization: Bearer header
Creating a reusable Axios instance that attaches the token automatically
Handling expired or invalid tokens with a 401 response
Removing the token on logout
---
What is a JSON Web Token (JWT)?
A JSON Web Token is a compact, encoded string that a server issues after a user logs in
successfully. It usually contains the user's identity and an expiry time, and is signed so the
server can verify it hasn't been tampered with. Instead of sending a username and password on
every request, the React app simply attaches this token to prove "this user is already
logged in." This is called token-based authentication, and it's the most common way
React apps authenticate with REST APIs today.
---
Step 1: Store the JWT After Login
When the login API call succeeds, the server returns a token in the response. We store it in
localStorage so it persists even after the page refreshes.
import axios from "axios";
const handleLogin = async (email, password) => {
try {
const response = await axios.post("https://api.example.com/login", {
email,
password,
});
const { token } = response.data;
// Save the JWT so we can reuse it on future requests
localStorage.setItem("authToken", token);
console.log("Login successful! Token saved.");
} catch (error) {
console.error("Login failed:", error.response?.data?.message);
}
};
export default handleLogin;
---
Step 2: Send the Token in the Authorization Header
Now that the token is saved, we attach it to any request that needs authentication using the
standard Authorization: Bearer <token> header format.
import axios from "axios";
const fetchUserProfile = async () => {
const token = localStorage.getItem("authToken");
const response = await axios.get("https://api.example.com/profile", {
headers: {
Authorization: `Bearer ${token}`,
},
});
return response.data;
};
export default fetchUserProfile;
---
Step 3: Create a Reusable Axios Instance
Manually adding the header on every request gets repetitive. Instead, let's create a single
axiosInstance.js file that automatically attaches the JWT to every outgoing
request using an interceptor.
import axios from "axios";
const axiosInstance = axios.create({
baseURL: "https://api.example.com",
});
// Attach the token automatically before every request
axiosInstance.interceptors.request.use(
(config) => {
const token = localStorage.getItem("authToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
export default axiosInstance;
Now, any component can simply do this — no need to repeat the header logic:
import axiosInstance from "./axiosInstance";
const fetchUserProfile = async () => {
const response = await axiosInstance.get("/profile");
return response.data;
};
---
Step 4: Handle Expired or Invalid Tokens
JWTs expire after a set time. When that happens, the API responds with a 401 Unauthorized
status. Let's add a response interceptor to catch that and redirect the user back to the
login page automatically.
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && error.response.status === 401) {
// Token expired or invalid — clear it and send the user to login
localStorage.removeItem("authToken");
window.location.href = "/login";
}
return Promise.reject(error);
}
);
---
Step 5: Remove the Token on Logout
When the user logs out, we simply remove the token from localStorage so future
requests are no longer authenticated.
const handleLogout = () => {
localStorage.removeItem("authToken");
window.location.href = "/login";
};
export default handleLogout;
---
Step 6: Full Example — axiosInstance.js
Here is the complete, ready-to-use axiosInstance.js file combining every step above.
import axios from "axios";
const axiosInstance = axios.create({
baseURL: "https://api.example.com",
});
// Attach JWT to every outgoing request
axiosInstance.interceptors.request.use(
(config) => {
const token = localStorage.getItem("authToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// Handle expired/invalid tokens on every response
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && error.response.status === 401) {
localStorage.removeItem("authToken");
window.location.href = "/login";
}
return Promise.reject(error);
}
);
export default axiosInstance;
---
How JWT Authentication Flow Works
| Step |
What Happens |
Where It Lives in Code |
| 1. Login |
User submits credentials; server returns a signed JWT |
handleLogin |
| 2. Store Token |
Token is saved in localStorage for reuse |
localStorage.setItem("authToken", token) |
| 3. Attach Token |
Every request automatically includes Authorization: Bearer <token> |
axiosInstance request interceptor |
| 4. Token Expiry |
A 401 response clears the token and redirects to login |
axiosInstance response interceptor |
| 5. Logout |
Token is removed, ending the authenticated session |
handleLogout |
---
Features and Learnings:-
Understood what a JSON Web Token (JWT) is and why it's used for authentication.
Stored the JWT securely in localStorage after a successful login.
Learned the standard Authorization: Bearer <token> header format.
Built a reusable Axios instance that attaches the auth token automatically.
Handled expired or invalid tokens using a response interceptor.
Cleared the token and redirected the user on logout.
Prepared the app for the next step: protecting routes with a PrivateRoute component.