117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
|
import fetch, {Response} from "node-fetch";
|
||
|
import useApp, {DEFAULT_ADDR, TestApp} from "./_app";
|
||
|
import Controller from "../src/Controller";
|
||
|
import CsrfProtectionComponent from "../src/components/CsrfProtectionComponent";
|
||
|
|
||
|
useApp(port => {
|
||
|
return new class extends TestApp {
|
||
|
protected async init(): Promise<void> {
|
||
|
this.use(new class extends Controller {
|
||
|
routes(): void {
|
||
|
this.get('/', (req, res, next) => {
|
||
|
res.render('test/csrf.njk');
|
||
|
}, 'csrf_test');
|
||
|
|
||
|
this.post('/', (req, res, next) => {
|
||
|
res.json({
|
||
|
status: 'ok',
|
||
|
});
|
||
|
}, 'csrf_test');
|
||
|
}
|
||
|
}());
|
||
|
|
||
|
await super.init();
|
||
|
}
|
||
|
|
||
|
|
||
|
protected registerComponents() {
|
||
|
super.registerComponents();
|
||
|
this.use(new CsrfProtectionComponent());
|
||
|
}
|
||
|
}(port);
|
||
|
});
|
||
|
|
||
|
describe('Test CSRF protection', () => {
|
||
|
let res: Response;
|
||
|
|
||
|
test('no csrf token should be in session at first', async () => {
|
||
|
res = await fetch(DEFAULT_ADDR, {
|
||
|
method: 'POST',
|
||
|
});
|
||
|
expect(res.status).toBe(401);
|
||
|
expect(await res.text()).toContain(`You weren't assigned any CSRF token.`);
|
||
|
});
|
||
|
|
||
|
let cookies: string | null;
|
||
|
|
||
|
test('sending no csrf token should fail', async () => {
|
||
|
cookies = res.headers.get('set-cookie');
|
||
|
expect(cookies).toBeDefined();
|
||
|
|
||
|
res = await fetch(`${DEFAULT_ADDR}${Controller.route('csrf_test')}`, {
|
||
|
headers: {
|
||
|
'Cookie': cookies!,
|
||
|
}
|
||
|
});
|
||
|
expect(res.ok).toBe(true);
|
||
|
|
||
|
res = await fetch(DEFAULT_ADDR, {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Cookie': cookies!,
|
||
|
}
|
||
|
});
|
||
|
expect(res.status).toBe(401);
|
||
|
expect(await res.text()).toContain(`You didn't provide any CSRF token.`);
|
||
|
});
|
||
|
|
||
|
test('sending an invalid csrf token should fail', async () => {
|
||
|
cookies = res.headers.get('set-cookie');
|
||
|
expect(cookies).toBeDefined();
|
||
|
|
||
|
res = await fetch(`${DEFAULT_ADDR}${Controller.route('csrf_test')}`, {
|
||
|
headers: {
|
||
|
'Cookie': cookies!,
|
||
|
}
|
||
|
});
|
||
|
expect(res.ok).toBe(true);
|
||
|
|
||
|
res = await fetch(DEFAULT_ADDR, {
|
||
|
method: 'POST',
|
||
|
body: JSON.stringify({
|
||
|
csrf: 'not_a_valid_csrf',
|
||
|
}),
|
||
|
headers: {
|
||
|
'Content-Type': 'application/json',
|
||
|
'Cookie': cookies!,
|
||
|
}
|
||
|
});
|
||
|
expect(res.status).toBe(401);
|
||
|
expect(await res.text()).toContain(`Tokens don't match.`);
|
||
|
});
|
||
|
|
||
|
test('sending a valid csrf token should success', async () => {
|
||
|
cookies = res.headers.get('set-cookie');
|
||
|
expect(cookies).toBeDefined();
|
||
|
|
||
|
res = await fetch(`${DEFAULT_ADDR}${Controller.route('csrf_test')}`, {
|
||
|
headers: {
|
||
|
'Cookie': cookies!,
|
||
|
}
|
||
|
});
|
||
|
expect(res.ok).toBe(true);
|
||
|
let csrf = await res.text();
|
||
|
|
||
|
res = await fetch(DEFAULT_ADDR, {
|
||
|
method: 'POST',
|
||
|
body: JSON.stringify({
|
||
|
csrf: csrf,
|
||
|
}),
|
||
|
headers: {
|
||
|
'Content-Type': 'application/json',
|
||
|
'Cookie': cookies!,
|
||
|
}
|
||
|
});
|
||
|
expect(res.ok).toBe(true);
|
||
|
});
|
||
|
});
|