How to test express form post with CSRF?

2019-02-14 05:21发布

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?

2条回答
混吃等死
2楼-- · 2019-02-14 05:32

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.

查看更多
欢心
3楼-- · 2019-02-14 05:39

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);
      });
});
查看更多
登录 后发表回答