发送csrfToken和set-cookie仍然是403无效的csrf令牌

时间:2019-02-14 01:23:59

标签: jestjs supertest csrf-token

对于使用csurf保护csrf(使用cookie选项)的登录表单,我正在尝试使用jest(测试环境:节点)通过集成测试。

我已经从登录表单和set-cookie标头中提取了csrfToken,但测试仍然失败,并显示403-无效的csrf令牌。

我看不出问题是什么,希望能朝正确的方向前进。

测试文件:

'{{ password }}'
const request   = require('supertest');
const {User}    = require('../../server/models/user');
const cheerio   = require('cheerio');
const app       = require('../../app');

let user, csrfToken, password, cookies;

beforeEach( async () => {
  user = await new User({
    firstName: "Name",
    lastName: "Surname",
    email: "email@example.com",
    password: "password",
    isAdmin : true
  }).save();
});

afterEach( async () => {
  await User.deleteMany();
});

describe('/login', () => {

  describe('GET /', () => {

    const exec = async () => {
      const res = await request(app).get(`/login`);
      let $ = cheerio.load(res.text);
      csrfToken = $('[name=_csrf]').val();
      return res;
    };

    it('should return the login form', async () => {
      const res = await exec();
      expect(res.status).toBe(200);
      expect(res.text).toMatch(/Sign In/);
    });
  });

  describe('POST /', () => {

    const getLoginCsrfs = async () => {
      const res = await request(app).get(`/login`);
      let $ = cheerio.load(res.text);
      csrfToken = $('[name=_csrf]').val();
      cookies = res.headers['set-cookie'];
      return res;
    };

    const postLogin = async () => {
      return request(app).post(`/login`)
        .set('Cookie', cookies)
        .send({ email: user.email,
                password: password,
                _csrf: csrfToken
        });
    };

    it('should return 401 without incorrect user info', async () => {
      await getLoginCsrfs();
      password = 'wrongpassword';
      const res = await postLogin();
      expect(res.status).toBe(401)
    });

    it('should return 403 without csrf token/header credentials', async () => {
      await getLoginCsrfs();
      csrfToken = '';
      cookies = '';
      password = 'password';
      const res = await postLogin();
      expect(res.status).toBe(403)
    });

    it('should return 200 with correct credentials', async () => {
      await getLoginCsrfs();
      password = 'password';
      const res = await postLogin();
      expect(res.status).toBe(200)
    });
  });
});

1 个答案:

答案 0 :(得分:0)

起初,我认为问题与set-cookie中的_csrf有关,但是在重新检查解决方案后很简单,

    const postLogin = async () => {
      return request(app).post(`/login`)
        .type('form')
        .set('Cookie', cookies)
        .send({ email: user.email,
                password: password,
                _csrf: csrfToken
        });
    };

我没有看到.type('form'),它与表单中的csrfToken有关(所有表单数据)都没有显示。

 PASS  tests/integration/login.test.js (5.661s)
  /login
    GET /
      ✓ should return the login form (489ms)
    POST /
      ✓ should return 401 without incorrect user info (443ms)
      ✓ should return 403 without csrf token/header credentials (131ms)
      ✓ should return 200 with correct credentials (255ms)

我一直在四处搜寻,并考虑了与开玩笑/超级测试和多个cookie有关的问题,但与以往一样,该解决方案更加简单明了,更贴近家庭。