From 262ba2c2afebcc01b99e590d162bc840bad54a5a Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Sun, 3 Nov 2019 19:20:44 -0400 Subject: [PATCH] Add captcha requirement for registering --- packages/common/src/APIDef.ts | 6 +++++ .../server/src/routes/configureAuthRoutes.ts | 13 ++++++++- packages/server/src/test-utils/TestUtils.ts | 27 ++++++++++++++++--- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/packages/common/src/APIDef.ts b/packages/common/src/APIDef.ts index 6919bb4..dece836 100644 --- a/packages/common/src/APIDef.ts +++ b/packages/common/src/APIDef.ts @@ -2,6 +2,12 @@ import { UserProfile, NewUser } from './user' import { Credentials } from './auth' export interface APIDef { + '/auth/captcha.svg': { + 'get': {} + } + '/auth/captcha.wav': { + 'get': {} + } '/auth/register': { 'post': { body: NewUser diff --git a/packages/server/src/routes/configureAuthRoutes.ts b/packages/server/src/routes/configureAuthRoutes.ts index 26f168a..d4608ba 100644 --- a/packages/server/src/routes/configureAuthRoutes.ts +++ b/packages/server/src/routes/configureAuthRoutes.ts @@ -1,13 +1,24 @@ import { APIDef, AuthService } from '@rondo.dev/common' import { Authenticator, ensureLoggedInApi } from '../middleware' import { AsyncRouter } from '../router' +import { espeak, image, audio, validateCaptcha } from '@rondo.dev/captcha' export function configureAuthRoutes( authService: AuthService, authenticator: Authenticator, t: AsyncRouter, ) { - t.post('/auth/register', async (req, res) => { + + t.get('/auth/captcha.svg', image({ + size: 6, + }) as any) + + t.get('/auth/captcha.wav', audio({ + commands: [espeak({})], + size: 6, + })) + + t.post('/auth/register', [validateCaptcha()], async (req, res) => { const user = await authService.createUser({ username: req.body.username, email: req.body.email, diff --git a/packages/server/src/test-utils/TestUtils.ts b/packages/server/src/test-utils/TestUtils.ts index 8f3cdb1..52e43aa 100644 --- a/packages/server/src/test-utils/TestUtils.ts +++ b/packages/server/src/test-utils/TestUtils.ts @@ -114,24 +114,37 @@ export class TestUtils { async registerAccount(username?: string) { const {context} = this - const {cookie, token} = await this.getCsrf() + const {cookie: csrfCookie, token} = await this.getCsrf() + + process.env.CAPTCHA = '1234' + const captcha = await supertest(this.app) + .get(`${context}/api/auth/captcha.svg`) + .expect(200) + + const sessionCookie = [ + csrfCookie, + this.getCookies(captcha.header['set-cookie']), + ].join('; ') const response = await supertest(this.app) .post(`${context}/api/auth/register`) - .set('cookie', cookie) + .set('cookie', sessionCookie) .send({ firstName: 'test', lastName: 'test', + captcha: process.env.CAPTCHA, email: username || this.username, ...this.getLoginBody(token, username), }) .expect(200) + console.log('registered?') + const cookies = this.getCookies(response.header['set-cookie']) return { headers: { - 'cookie': [cookies, cookie].join('; '), + 'cookie': [cookies, sessionCookie].filter(c => !!c).join('; '), 'x-csrf-token': token, }, userId: response.body.id, @@ -197,7 +210,13 @@ export class TestUtils { return service as RPCClient } - private getCookies(setCookiesString: string[]): string { + private getCookies(setCookiesString: string | string[]): string { + if (!setCookiesString) { + return '' + } + if (typeof setCookiesString === 'string') { + setCookiesString = [setCookiesString] + } return setCookiesString.map(c => c.split('; ')[0]).join('; ') }