Giter Site home page Giter Site logo

Comments (19)

george-norris-salesforce avatar george-norris-salesforce commented on April 27, 2024 2

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..
image

sending cookie ok via Ajax.. it does get sent to the server in the headers.
image

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.

dougwilson avatar dougwilson commented on April 27, 2024 1

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.

dougwilson avatar dougwilson commented on April 27, 2024

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.

dougwilson avatar dougwilson commented on April 27, 2024

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.

george-norris-salesforce avatar george-norris-salesforce commented on April 27, 2024

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.

dougwilson avatar dougwilson commented on April 27, 2024

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.

newyork-anthonyng avatar newyork-anthonyng commented on April 27, 2024

@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.

dougwilson avatar dougwilson commented on April 27, 2024

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.

newyork-anthonyng avatar newyork-anthonyng commented on April 27, 2024

@dougwilson

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.

dougwilson avatar dougwilson commented on April 27, 2024

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.

dougwilson avatar dougwilson commented on April 27, 2024

You can see the list of options the res.sendFile method takes here: http://expressjs.com/en/4x/api.html#res.sendFile

from csurf.

newyork-anthonyng avatar newyork-anthonyng commented on April 27, 2024

@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.

iDVB avatar iDVB commented on April 27, 2024

Does anyone have this working that can share and example?

from csurf.

phun-ky avatar phun-ky commented on April 27, 2024

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.

sn00pee avatar sn00pee commented on April 27, 2024

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.

conoverm avatar conoverm commented on April 27, 2024

@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.

dantman avatar dantman commented on April 27, 2024

@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.

AndrewHaine avatar AndrewHaine commented on April 27, 2024

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.

prufrock123 avatar prufrock123 commented on April 27, 2024

@AndrewHaine,

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.