I use React Single Page Application as a client side or Create React App (CRA).
In my backend i use Node.js & Express.
to fetch data or store i need to call API from client to backend.
actually I've seen there are several middleware like: - Express CSURF
but to be honest I don't understand how to send a CSRF token to the client every request. I have tried several times, by inserting the CSRF into a cookie and then taking it on the client side. but when the first request or new cookie is stored, I get error Invalid CSRF Token
.
and even though I did this:
app.use(session({
genid: function (req) {
return uuidv4() // use UUIDs for session IDs
},
name:keys.session.name,
secret: keys.session.secret,
resave: false,
saveUninitialized: true,
rolling:true,
cookie: {
secure: false,
httpOnly: true,
maxAge:keys.session.maxAge, // satu hari,
sameSite:true,
}
}));
app.use(passport.session());
app.use(cookieParser());
app.use(csrf({ cookie: false }));
app.use((req,res,next)=>{
res.cookie('CSRF_token', req.csrfToken(), { sameSite: true });
})
Which means the CSRF_token cookie will change each request. but I only set it once like this : axios.defaults.headers.common['csrf-token'] = csrf;
and the results its still work, which should not working.
So do I need CSRF? or how to configure the correct one on react SPA.
To protect against CSRF attacks we need to ensure there is something in the request that the evil site is unable to provide. One solution is to use the Synchronizer Token Pattern. This solution is to ensure that each request requires, in addition to our session cookie, a randomly generated token as an HTTP parameter.
Luckily, it's easy to implement CSRF protection in React. You only have to store the CSRF token in your React app and generate relevant headers to send along with the request to the server. The server will quarantine all CSRF requests.
Enabling cross-site request forgery (CSRF) protection is recommended when using REST APIs with cookies for authentication. If your REST API uses the WCToken or WCTrustedToken tokens for authentication, then additional CSRF protection is not required.
There's no way someone can abuse XSS and take your JWT to impersonate you. If you put your JWTs in a header, you don't need to worry about CSRF. You do need to worry about XSS, however. If someone can abuse XSS to steal your JWT, this person is able to impersonate you.
So do I need CSRF?
As stated here: Am I under risk of CSRF attacks in a POST form that doesn't require the user to be logged in? I think you should still set it.
As for why it is not working for you, I assume it is because of the header name. You may check what CSURF checks by default.
The default value is a function that reads the token from the following locations, in order:
- req.body._csrf - typically generated by the body-parser module.
- req.query._csrf - a built-in from Express.js to read from the URL query string.
- req.headers['csrf-token'] - the CSRF-Token HTTP request header.
- req.headers['xsrf-token'] - the XSRF-Token HTTP request header.
- req.headers['x-csrf-token'] - the X-CSRF-Token HTTP request header.
- req.headers['x-xsrf-token'] - the X-XSRF-Token HTTP request header.
Going by what CSURF checks, you have a variety of options to choose from, and looking at axios, it seems to have a couple options for setting xsrf cookie and header names.
...
// `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
...
For example, in order to use the X-XSRF-TOKEN
header key axios comes with by default, I used the following method in my App.js file:
componentDidMount() {
axios.get(`/api/csrf`) // Send get request to get CSRF token once site is visited.
.then(res => {
axios.defaults.headers.post['X-XSRF-TOKEN'] = res.data; // Set it in header for the rest of the axios requests.
})
}
You could, however, use a form hidden input or any other method you're comfortable with. You can read more about why it's common to put them in cookies here.
I'm not sure what you're using for your client, but if you're using Redux, you may look here for help. If it doesn't work, you may Google other methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With