FunnyDEV
FunnyDEV

Reputation: 29

Getting "ForbiddenError: invalid csrf token" with doubleCsrf in Express.js

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

Backend:

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);

Frontend (Vue)

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

Answers (0)

Related Questions