NodeJS Express Application Testing - How to submit CSRF token when testing with Mocha and Chai?
<p>I'm trying to write a test for a <code>POST</code> route in my Express application using Mocha, Chai and ChaiHttp, but I can't get it to work due to the fact that I keep getting an <code>HTTP 403</code> response whenever submitting my CSRF token. Below is the code that I have up until now:</p>

<p><strong>express.js configuration file</strong></p>

<pre><code>...
  app.use(session(config.SESSION));
  // csrf is the 'csurf' module
  app.use(csrf());

  app.use((req, res, next) =&gt; {
    res.cookie('XSRF-TOKEN', req.csrfToken());
    return next();
  });
...
</code></pre>

<p><strong>User.test.js</strong></p>

<pre><code>'use strict';
process.env.NODE_ENV = 'test';

const User = require('../server/models/User');
const chai = require('chai');
const chaiHttp = require('chai-http');
const server = require('../index');
const utils = require('../utils');

chai.use(chaiHttp);

describe('Users', () =&gt; {
  beforeEach((done) =&gt; {
    User.remove({}, (err) =&gt; {
      done();
    });
  });

  after((done) =&gt; {
    server.close();
    done();
  });
...
 /*
   * [POST] /user
   */
  describe('[POST] /user', () =&gt; {
    it('should return a JSON object with a "success" property equal to "true" when creating a new user', (done) =&gt; {
      const userObj = utils.generateUserObject();

      chai.request(server)
          .get('/api')
          .end((error, response) =&gt; {

            userObj._csrf = utils.extractCsrfToken(response.headers['set-cookie']);


            /*
             * Accurately logs the _csrf property with the correct CSRF token that was retrieved via the initial GET request
             * 
             * Example output:
             * 
             * { 
             * username: 'Stacey89',
             * first_name: 'Gregg',
             * last_name: 'King',
             * ...
             * _csrf: 'vBhDfXUq-jE86hOHadDyjgpQOu-uE8FyUp_M' 
             * }
             *
             */ 


            console.log(userObj);

            chai.request(server)
                .post('/api/user')
                .set('content-type', 'application/x-www-form-urlencoded')
                .send(userObj)
                .end((err, res) =&gt; {
                  res.should.have.status(200);
                  res.body.should.be.a('object');
                  res.body.should.have.property('success').eql('true');
                  done();
                });
          });
    });
...
</code></pre>

<p><strong>utils.js</strong></p>

<pre><code>...
  extractCsrfToken(cookiesObj) {
    const cookiesArray = Array.prototype.join.call(cookiesObj, '').split(';');
    let csrfToken = 'NOT FOUND';

    cookiesArray.forEach((cookie) =&gt; {
      if (cookie.includes('XSRF-TOKEN')) {
        csrfToken = cookie.split('=').splice(1, 1).join('');
      }
    });

    return csrfToken;
  }
...
</code></pre>

<p>When I run the above test, I get the following error:</p>

<pre><code>ForbiddenError: invalid csrf token
...
POST /api/user 403
</code></pre>

<p>The strange thing is that if I do a POST request from Postman with the exact same configuration as the one previously described, I successfully get the response I am looking for and the form submission succeeds.</p>

<p>It appears to not be working only when submitting the <code>userObj</code> from my test suite.</p>

<p><strong>UPDATE #1</strong>
I finally managed to find a working solution for my issue.</p>

<p>I've updated the middleware that was previously setting the <code>XSRF-TOKEN</code> cookie to the following:</p>

<pre><code>  app.use((err, req, res, next) =&gt; {
    res.locals._csrf = req.csrfToken();
    return next();
  });
</code></pre>

<p>Now the unit test runs successfully.</p>

<p>Moreover, I noticed that the first <code>[GET]</code> request issued to the server returns the <code>Set-Cookie</code> header:</p>

<pre><code>Status Code: 200 OK
Content-Length: 264
Content-Type: application/json; charset=utf-8
Date: Tue, 18 Oct 2016 12:10:09 GMT
Etag: W/"108-NSQ2HIdRqiuMIf0F+7qwjw"
Set-Cookie: connect.sid=s%3Ap5io8_3iD7Wy0X0K77qWZLoYj-fD1ZbA.6uvcBiB%2B%2BSi1KOVOmJgvWe%2B5Mqpuc1rs9yUYxH0uNPY; Path=/; HttpOnly
X-Download-Options: noopen
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
x-dns-prefetch-control: off
x-frame-options: SAMEORIGIN
</code></pre>

<p>Any subsequent <code>[GET]</code> request does not return that header:</p>

<pre><code>Status Code: 200 OK
Content-Length: 264
Content-Type: application/json; charset=utf-8
Date: Tue, 18 Oct 2016 12:11:19 GMT
Etag: W/"108-NSQ2HIdRqiuMIf0F+7qwjw"
X-Download-Options: noopen
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
x-dns-prefetch-control: off
x-frame-options: SAMEORIGIN
</code></pre>

<p>Is this ok in terms of application security? Is it a good practice to simply set the <code>_csrf</code> token on the <code>res.locals</code> object?</p>