Search code examples
javascriptexpresssupertest

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?


Solution

  • 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);
          });
    });