Secure Authentication in CampusX Using JWT
Introduction Authentication is a critical part of any web application. In CampusX, we use JWT (JSON Web Tokens) to handle user authentication efficiently and securely. JWT provides a stateless way to verify users while minimizing database queries. This blog explains: What JWT is and why it's important. How CampusX uses access and refresh tokens. How token refreshing ensures seamless user experience. What is JWT? JWT is a compact and self-contained token format used for securely transmitting information between parties as a JSON object. It consists of three parts: Header – Contains metadata like token type and signing algorithm. Payload – Stores claims (user information, expiry time, etc.). Signature – Ensures token integrity using a secret key. Example of a JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiIxMjM0IiwiaWF0IjoxNjExNjE2MDB9 .4xvNcTkORHj9xE8TftRkEw7sdJjxUX9PYG6xRJOnhZk JWT is commonly used for authentication because it eliminates the need for session storage and repeated database queries. Access & Refresh Tokens in CampusX CampusX uses access tokens for authentication and refresh tokens for renewing access tokens without requiring the user to log in again. 1. Generating Tokens const generateAccessAndRefreshTokens = async (userId) => { try { const user = await User.findById(userId); const accessToken = user.generateAccessToken(); const refreshToken = user.generateRefreshToken(); user.refreshToken = refreshToken; await user.save({ validateBeforeSave: false }); return { accessToken, refreshToken }; } catch (error) { throw new ApiError( STATUS_CODES.INTERNAL_ERROR, "Error generating access and refresh tokens" ); } }; Here, the user's access and refresh tokens are generated and stored securely. JWT Authentication Middleware The verifyJWT middleware protects routes by verifying JWT tokens before allowing access. export const verifyJWT = AsyncHandler(async (req, res, next) => { try { const token = req.cookies?.accessToken || req.header("Authorization")?.replace("Bearer ", ""); if (!token) { throw new ApiError(401, "Unauthorized request"); } const decodedToken = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET); const user = await User.findById(decodedToken._id).select("-password -refreshToken"); if (!user) { throw new ApiError(402, "Invalid access token"); } req.user = user; next(); } catch (error) { throw new ApiError(401, "Token expired"); } }); This ensures only authenticated users can access protected resources. Refreshing Expired Tokens If the access token expires, CampusX uses the refresh token to generate a new access token, avoiding user logouts. const refreshAccessToken = AsyncHandler(async (req, res) => { const incomingRefreshToken = req.cookies.refreshToken || req.body.refreshToken; if (!incomingRefreshToken) { throw new ApiError(STATUS_CODES.UNAUTHORIZED, "Refresh token not found"); } try { const decodedToken = jwt.verify(incomingRefreshToken, process.env.REFRESH_TOKEN_SECRET); const user = await User.findById(decodedToken._id); if (!user || incomingRefreshToken !== user.refreshToken) { throw new ApiError(STATUS_CODES.UNAUTHORIZED, "Invalid refresh token"); } const { accessToken, refreshToken } = await generateAccessAndRefreshTokens(user._id); res .status(STATUS_CODES.OK) .cookie("accessToken", accessToken, { httpOnly: true, secure: true }) .cookie("refreshToken", refreshToken, { httpOnly: true, secure: true }) .json(new ApiResponse(STATUS_CODES.OK, { accessToken, refreshToken }, "Access token refreshed")); } catch (error) { throw new ApiError(STATUS_CODES.INTERNAL_ERROR, "Error refreshing access token: " + error.message); } }); Fetching User on Page Refresh CampusX calls fetchUser on every page load to refresh expired access tokens. const fetchUser = async () => { try { const res = await axiosInstance.get("/users/current-user"); setUser(res.data?.data?.user); } catch (err) { if (err.response?.status === 401) { setUser(null); } if (err.response?.status === 403) { console.log("Access Token Expired, Refreshing..."); try { await axiosInstance.post("/users/refresh-token"); return fetchUser(); // Retry the original request } catch (refreshErr) { toast.error("Session expired, Please login again!"); } } throw err; } }; How it Works: Calls /users/current-user to check if the user is logged in. If the access token is expired (403 error), it tries to refresh it using /users/refresh-token. If refreshing fails, prompts the user to log in again. Conclusion JWT authentication in CampusX ensures: ✅ Secure user authentication. ✅ Efficient token-based sessio

Introduction
Authentication is a critical part of any web application. In CampusX, we use JWT (JSON Web Tokens) to handle user authentication efficiently and securely. JWT provides a stateless way to verify users while minimizing database queries.
This blog explains:
- What JWT is and why it's important.
- How CampusX uses access and refresh tokens.
- How token refreshing ensures seamless user experience.
What is JWT?
JWT is a compact and self-contained token format used for securely transmitting information between parties as a JSON object. It consists of three parts:
- Header – Contains metadata like token type and signing algorithm.
- Payload – Stores claims (user information, expiry time, etc.).
- Signature – Ensures token integrity using a secret key.
Example of a JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiIxMjM0IiwiaWF0IjoxNjExNjE2MDB9
.4xvNcTkORHj9xE8TftRkEw7sdJjxUX9PYG6xRJOnhZk
JWT is commonly used for authentication because it eliminates the need for session storage and repeated database queries.
Access & Refresh Tokens in CampusX
CampusX uses access tokens for authentication and refresh tokens for renewing access tokens without requiring the user to log in again.
1. Generating Tokens
const generateAccessAndRefreshTokens = async (userId) => {
try {
const user = await User.findById(userId);
const accessToken = user.generateAccessToken();
const refreshToken = user.generateRefreshToken();
user.refreshToken = refreshToken;
await user.save({ validateBeforeSave: false });
return { accessToken, refreshToken };
} catch (error) {
throw new ApiError(
STATUS_CODES.INTERNAL_ERROR,
"Error generating access and refresh tokens"
);
}
};
Here, the user's access and refresh tokens are generated and stored securely.
JWT Authentication Middleware
The verifyJWT
middleware protects routes by verifying JWT tokens before allowing access.
export const verifyJWT = AsyncHandler(async (req, res, next) => {
try {
const token = req.cookies?.accessToken || req.header("Authorization")?.replace("Bearer ", "");
if (!token) {
throw new ApiError(401, "Unauthorized request");
}
const decodedToken = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
const user = await User.findById(decodedToken._id).select("-password -refreshToken");
if (!user) {
throw new ApiError(402, "Invalid access token");
}
req.user = user;
next();
} catch (error) {
throw new ApiError(401, "Token expired");
}
});
This ensures only authenticated users can access protected resources.
Refreshing Expired Tokens
If the access token expires, CampusX uses the refresh token to generate a new access token, avoiding user logouts.
const refreshAccessToken = AsyncHandler(async (req, res) => {
const incomingRefreshToken = req.cookies.refreshToken || req.body.refreshToken;
if (!incomingRefreshToken) {
throw new ApiError(STATUS_CODES.UNAUTHORIZED, "Refresh token not found");
}
try {
const decodedToken = jwt.verify(incomingRefreshToken, process.env.REFRESH_TOKEN_SECRET);
const user = await User.findById(decodedToken._id);
if (!user || incomingRefreshToken !== user.refreshToken) {
throw new ApiError(STATUS_CODES.UNAUTHORIZED, "Invalid refresh token");
}
const { accessToken, refreshToken } = await generateAccessAndRefreshTokens(user._id);
res
.status(STATUS_CODES.OK)
.cookie("accessToken", accessToken, { httpOnly: true, secure: true })
.cookie("refreshToken", refreshToken, { httpOnly: true, secure: true })
.json(new ApiResponse(STATUS_CODES.OK, { accessToken, refreshToken }, "Access token refreshed"));
} catch (error) {
throw new ApiError(STATUS_CODES.INTERNAL_ERROR, "Error refreshing access token: " + error.message);
}
});
Fetching User on Page Refresh
CampusX calls fetchUser
on every page load to refresh expired access tokens.
const fetchUser = async () => {
try {
const res = await axiosInstance.get("/users/current-user");
setUser(res.data?.data?.user);
} catch (err) {
if (err.response?.status === 401) {
setUser(null);
}
if (err.response?.status === 403) {
console.log("Access Token Expired, Refreshing...");
try {
await axiosInstance.post("/users/refresh-token");
return fetchUser(); // Retry the original request
} catch (refreshErr) {
toast.error("Session expired, Please login again!");
}
}
throw err;
}
};
How it Works:
- Calls
/users/current-user
to check if the user is logged in. - If the access token is expired (403 error), it tries to refresh it using
/users/refresh-token
. - If refreshing fails, prompts the user to log in again.
Conclusion
JWT authentication in CampusX ensures:
✅ Secure user authentication.
✅ Efficient token-based session management.
✅ Seamless token refresh without re-login.
By implementing access & refresh tokens, CampusX provides a smooth user experience while maintaining strong security.