Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test express form post with CSRF?

I'm trying to write a test for my server side form validation but I keep getting a Forbidden error. It seems that this needs to be a 2 step process. Step 1, acquire the CSRF value from the form. Step 2, use the CSRF value to post to the form handler. However no matter how I try to post I get a forbidden error.

--full test: https://github.com/socketwiz/swblog/blob/master/test/contact.js#L57-L100

I've tried changing the following line thusly: https://github.com/socketwiz/swblog/blob/master/test/contact.js#L85

.send({name: 'foo', 'X-CSRF-Token': token})

.set('X-CSRF-Token', token)

.set('Cookie', ['X-CSRF-Token=' + token])

But nothing I try will seem to satisfy the CSRF requirement. The more I try the more complex this gets for what seems like a simple thing. Maybe I'm going about this all wrong. Any ideas?

like image 930
Ricky Nelson Avatar asked Apr 17 '14 02:04

Ricky Nelson


People also ask

How use CSRF token in Express JS?

In order to function properly, the CSRF token must be generated by the server and then rendered on the page where the form is held. Then, all requests from that page will have the input with the csrf_token name included in the request, and all requests which are made cross-site will not have it.

How do I know if my CSRF token is working?

A couple of ways you can test it: Open the developer tools in your browser find the input element for the CSRF token and edit the token value. Trigger a POST submission. This should cause an error, HTTP status 403 typically.

How use CSRF token in node JS?

To implement CSRF tokens in Node. js, we can use the csurf module for creating and validating tokens. Lines of code in an integrated development environment. Notice that we added the routing code here, but you can have it in a separate routing class index.

Which CSRF middleware function do we use to create a token for a form?

csrfToken() function to make a token which should be added to requests which mutate state, within a hidden form field, query-string etc. This token is validated against the visitor's session or csrf cookie.


2 Answers

Thanks @shawnzhu, you comment on cookies helped me figure out what I needed to do. I had an idea that I was over complicating it. Here is what I came up with:

https://github.com/socketwiz/swblog/blob/master/test/contact.js

it('should not post just a name', function(done) {
    request(mock)
      .get('/contact')
      .end(function(err, res){
        var $html = jQuery(res.text);
        var csrf = $html.find('input[name=_csrf]').val();

        request(mock)
          .post('/api/contact.json')
          .set('cookie', res.headers['set-cookie'])
          .send({
            _csrf: csrf,
            name: 'Mary Jane'
          })
          .expect(function(res){
            assert.equal(undefined, res.body.name);
            assert.equal('You must provide a valid email address', res.body.email);
            assert.equal('You must provide a message', res.body.message);
          })
          .expect(500, done);
      });
});
like image 125
Ricky Nelson Avatar answered Oct 01 '22 21:10

Ricky Nelson


The express csrf middleware saves a secret in session to validate csrf token, while I guess you use cookieSession middleware as session store. So you need to resend the session cookies when POST the data with csrf token, the express can use the secret in session to validate your csrf token.

like image 25
shawnzhu Avatar answered Oct 01 '22 21:10

shawnzhu