Thursday, 21 April 2022

How to exclude an endpoint from CSRF middleware

See update below...

My React front-end is able to call upon my Node back-end API. However, when an external site calls upon my API, it receives an error (for POST requests but not for GET requests).

App setup includes:

const express = require("express");
const cookieParser = require("cookie-parser");
const csurf = require("csurf");
var cors = require("cors");

var corsOptions = {
    origin: process.env.CORS_ORIGIN_URL.split(","),
    credentials: true,
    exposedHeaders: ["set-cookie"],
};
app.use(cors(corsOptions));

app.use(
    cookieParser(process.env.COOKIE_SECRET, {
        sameSite: true,
        httpOnly: true,
        secure: process.env.NODE_ENV === "production",
        maxAge: process.env.COOKIE_MAX_AGE,
    })
);

// If I comment out the next 5 lines, external services CAN call upon my API
app.use(csurf({ cookie: true }));
app.use(function (req, res, next) {
    res.cookie("XSRF-TOKEN", req.csrfToken());
    next();
});

app.use("/api/csrf", (req, res) => {
    return res.status(200).json({
        status: true,
        csrfToken: req.csrfToken(),
    });
});

app.use("/api", api);

If I comment out the CSRF part (the 5 lines) of the setup, then external services ARE able to call upon my API. How should I adjust this CSRF setup to make my application work also with "external" API calls?


Update

I've updated the CSRF configuration to the setup below. Would this be a secure setup? The idea is to use CSRF except for endpoints that need to be reachable to external services. res.cookie("XSRF-TOKEN", req.csrfToken()); no longer seems to work.

app.use(
    cookieParser(process.env.COOKIE_SECRET, {
        sameSite: true,
        httpOnly: true,
        secure: process.env.NODE_ENV === "production",
        maxAge: process.env.COOKIE_MAX_AGE,
    })
);

var csrf = csurf({ cookie: true });

app.use(function (req, res, next) {
    if (req.url === '/api/mollie_webhook') {
        return next();
    } else {
        app.use(csrf);
        // I think this is not allowed, since we already have app.use 4 lines up, but don't know how else to do this...

        // it correctly gets to this point
        res.cookie("XSRF-TOKEN", req.csrfToken());
        // but then not to this point

        app.use("/api/csrf", (req, res) => {
            return res.status(200).json({
                status: true,
                csrfToken: req.csrfToken(),
            });
        });
    }
});

app.use("/api", api);


from How to exclude an endpoint from CSRF middleware

No comments:

Post a Comment