Comments (19)
Ok maybe we can start fleshing out what to do here..
I'm doing this, and it is not working.. ↓↓↓↓
Sending cookie on index route..
//server
app.use(cookieParser());
const csrfProtection = csrf({ cookie: true });
app.get('*', csrfProtection, (req, res) => {
res.sendFile(
resolve(__dirname, '../build/index.html'),
{ csrfToken: req.csrfToken() }
);
});
Cookie is stored correctly on the client..
sending cookie ok via Ajax.. it does get sent to the server in the headers.
The route that recieves request..
app.post(`upload_photo`,
uploadHandler.single('file'),
csrfProtection,
(req, res) => {
.....
Results in 403
Tried changing headers to ..
req.headers['csrf-token']
req.headers['XSRF-Token']
req.headers['x-csrf-token]
Still results in 403
from csurf.
Basically the token is not the same as the token secret, they are different value. The value you need to put in the header back had to be the value you got from the req.csrfToken() call, not from the _csrf cookie, which is not the same value and will be rejected.
from csurf.
Hi @george-norris-salesforce I think that's a good suggestion :) I haven't personally used it very much with Ajax, so anyone who wants to provide a nice example / docs would be awesome 👍
from csurf.
The cookie in your example only is storing the token secret, not the token itself. You get the token from req.csrfToken() and that is the value you would need to send back to the server.
from csurf.
Unless I'm not understanding this example, the req.csrfToken()
is used to initially set the cookie and the protected routes use the csrfProtection
middleware to look for a header with one of these names. The example appears to do be doing this too..
Here is what I'm doing step by step..
1). The index get
route (which is always first route in single page app) is hit. req.csrfToken()
is called and sends back token. Similar to /form
get route in this example.
2). Instead of using a hidden field in a standard form submit, we read cookie from browser and add it to headers and make ajax request.. the header name keeps with these conventions.
3). csrfProtection
is inserted as middleware in the route, similar to the /process
route in this example.
from csurf.
The example is using the value from the req.csrfToken() call via the form element, which is the token. You had no code doing that. The readme explains that the _csrf cookie is the token secret, not the token.
from csurf.
@dougwilson I'm looking to implement something similar too and was confused when reading through this issue.
In the example from the README.md
, you're saying the req.csrfToken()
is generating the actual token.
But in the code snippet posted by @george-norris-salesforce, the req.csrfToken()
call he is using is only creating a token secret?
If so, why the difference? And how would I generate the actual token if I only have the token secret?
from csurf.
Hi @newyork-anthonyng the token is generated from req.csrfToken()
call, which is the value you need to submit back to the server. The code snippet from @george-norris-salesforce is not correct.
from csurf.
I see in his code snippet that he's using:
app.get('*', csrfProtection, (req, res) => {
res.sendFile(
resolve(__dirname, '../build/index.html'),
{ csrfToken: req.csrfToken() }
);
});
The req.csrfToken()
is there. I might be missing something obvious here.
from csurf.
Hi @newyork-anthonyng the res.sendFile
method as defined in the Express.js API does not take a csrfToken
option, so that option is doing nothing. You may as well be doing res.sendFile(file, { fooBarBaz: req.csrfToken() })
.
from csurf.
You can see the list of options the res.sendFile
method takes here: http://expressjs.com/en/4x/api.html#res.sendFile
from csurf.
@dougwilson Thanks! I totally missed the res.sendFile
part.
@george-norris-salesforce Did you start on the PR for updating the docs? If not, I'd like to help.
from csurf.
Does anyone have this working that can share and example?
from csurf.
I'm having the same problem; Making a react SPA with webpack and hosting on node/express, need a way to let the view get req.csrfToken()
from csurf.
One thing that seems to be left out is that you need to pass both the csrfToken AND the _csrf cookie.
The cookie should be found in the response.headers['set-cookie'].
from csurf.
@phun-ky Angular automatically looks for a cookie with the name XSRF-TOKEN and then translates it to an X-XSRF-token header. I don't know if there's a React library that does this. The following may help you out a bit.
app.use(cookieParser())
app.use(csurf({ cookie: true }))
app.use(function (req, res, next) {
if (!req.cookies['_csrf']) return next();
res.setHeader('Set-Cookie', [
'XSRF-TOKEN='+ req.csrfToken() + ';' +
'path=/'
]);
next();
})
app.use(function (err, req, res, next) {
if (err.code !== 'EBADCSRFTOKEN') {
return next(err)
} else {
res.writeHeader(403);
res.write(err.toString());
res.end();
}
})
from csurf.
@phun-ky Angular automatically looks for a cookie with the name XSRF-TOKEN and then translates it to an X-XSRF-token header. I don't know if there's a React library that does this. The following may help you out a bit.
React doesn't do HTTP requests. You use whatever XHR/fetch api you want.
axios does something similar with a cookie and header.
from csurf.
I was having this issue too but realised I wasn't sending the token secret with my ajax call.
Sending the token through a header wasn't enough, you also need to send the token secret which is stored in the _csrf cookie or in req.session (depending on whether you set 'cookie' to true or false in the middleware options)
The fix for me was to include the credentials (which sends the cookie / session data) with the ajax request. I'm using the fetch api but there are ways to do this with jQuery, axios etc. If this is the fix you're looking for I'm happy to do a PR updating the docs.
Example:
/* Set a header including the token */
const headers = new Headers();
headers.append('csrf-token', _token_); // _token_ represents the token returned from req.csrfToken()
/* Make the request */
fetch('/protectedAPI', {
credentials: 'same-origin', // Sends the cookie which includes the token secret
headers: headers,
method: 'POST'
});
from csurf.
It seems like you are saying that the solution is to store both the csrf token AND secret as cookies in the client. But doesn't this defeat the purpose of the CSRF protection?
The idea is you shouldn't be able to make a request simply by using the cookies stored in a client. The idea is supposed to be that a request requires a cookie in the client AND a value from the submitted request to succeed.
from csurf.
Related Issues (20)
- Feature add 'Encrypted Token Pattern' HOT 3
- Add credentials warning to documentation HOT 7
- A way of getting csrfToken through POST request HOT 3
- Cannot validate CSRF token using the example code HOT 4
- Can docs clarify how cookie mode works? HOT 3
- please document the `signed` config option HOT 4
- Disable CSRF checking during tests HOT 1
- previous token still valid HOT 1
- Token Lifetime HOT 2
- Need docs and examples for working with single page application. HOT 3
- BREACH attack mitigation HOT 2
- No regeneration of secret when a valid token is submitted HOT 2
- A cookie secret is not really secret HOT 1
- Upgrade to [email protected] for SameSite=None support HOT 1
- Best practice for the csrf token and secret (signed? httponly?) HOT 1
- User's CSRF Token is invalid but doesn't look like so HOT 7
- New token secret with every request HOT 3
- Update docs to address situations with mixed protection approaches HOT 1
- How I can validate csrf token one time with only a request
- Failed on validation when using with 2 backends
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from csurf.