Reputation: 29
I'm having an issue with doubleCsrf
in my Express.js backend, and I keep getting the following error on every request:
ForbiddenError: invalid csrf token
at doubleCsrf (file:///Users/admin/Documents/backend/node_modules/csrf-csrf/lib/esm/index.js:13:35)
at file:///Users/admin/Documents/backend/routes/auth/csrfMiddleware.js:10:5
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:113:12) {
code: 'EBADCSRFTOKEN
Here is my middleware setup in csrfMiddleware.js:
import { doubleCsrf } from "csrf-csrf";
import dotenv from 'dotenv';
dotenv.config();
const {
doubleCsrfProtection,
generateToken,
invalidCsrfTokenError
} = doubleCsrf({
getSecret: () => process.env.VITE_CSRF_SECRET,
cookieName: "XSRF-TOKEN",
cookieOptions: {
httpOnly: false,
secure: false,
sameSite: "Lax",
path: "/",
partitioned: true,
},
ignoredMethods: ["GET", "HEAD", "OPTIONS"],
getTokenFromRequest: (req) => {
console.log("CSRF-token from request headers:", req.headers["x-csrf-token"]);
console.log("CSRF-token from cookies:", req.cookies["XSRF-TOKEN"]);
return req.cookies["XSRF-TOKEN"];
},
});
export { doubleCsrfProtection, generateToken, invalidCsrfTokenError };
Then in** server.js,** I generate and store the CSRF token in a cookie:
app.get('/api/auth/csrf-token', (req, res) => {
const csrfToken = generateToken(req, res);
res.clearCookie("XSRF-TOKEN");
res.cookie("XSRF-TOKEN", csrfToken, {
httpOnly: false,
secure: false,
sameSite: "Lax",
path: "/"
});
res.json({ csrfToken });
});
// 📌 **API routes**
app.use('/api', apiRouter);
// ✅ CSRF protection applied here
app.use(doubleCsrfProtection);
On the frontend, I'm fetching the CSRF token before making any API requests:
import axios from 'axios';
const baseURL = import.meta.env.VITE_API_BASE_URL;
const axiosInstance = axios.create({
baseURL,
withCredentials: true,
});
let isFetchingCsrfToken = false;
const fetchCsrfToken = async () => {
if (isFetchingCsrfToken) return;
isFetchingCsrfToken = true;
try {
const response = await axiosInstance.get('/auth/csrf-token');
if (response.data.csrfToken) {
document.cookie = `XSRF-TOKEN=${response.data.csrfToken}; path=/`;
axiosInstance.defaults.headers.common['X-CSRF-Token'] = response.data.csrfToken;
console.log('CSRF-token set:', response.data.csrfToken);
}
} catch (error) {
console.error('Error fetching CSRF token:', error);
} finally {
isFetchingCsrfToken = false;
}
};
fetchCsrfToken();
export default axiosInstance;
When I log document.cookie
in the console tab, I can see the token correctly set.
Also The backend logs show that the token is received in the request headers and cookies
What could be the issue?
Upvotes: 0
Views: 24