diff --git a/lib/new-admin/graphql/modules/authentication.js b/lib/new-admin/graphql/modules/authentication.js index a02be3a4..e0237b7c 100644 --- a/lib/new-admin/graphql/modules/authentication.js +++ b/lib/new-admin/graphql/modules/authentication.js @@ -61,11 +61,15 @@ const getUserData = context => { } const get2FASecret = (username, password) => { - return authenticateUser(username, password).then(user => { - const secret = otplib.authenticator.generateSecret() - const otpauth = otplib.authenticator.keyuri(user.username, 'Lamassu Industries', secret) - return { secret, otpauth } - }) + return authenticateUser(username, password) + .then(user => { + const secret = otplib.authenticator.generateSecret() + const otpauth = otplib.authenticator.keyuri(user.username, 'Lamassu Industries', secret) + return Promise.all([users.saveTemp2FASecret(user.id, secret), secret, otpauth]) + }) + .then(([_, secret, otpauth]) => { + return { secret, otpauth } + }) } const confirm2FA = (token, context) => { @@ -112,6 +116,9 @@ const validateReset2FALink = token => { .then(user => { const secret = otplib.authenticator.generateSecret() const otpauth = otplib.authenticator.keyuri(user.username, 'Lamassu Industries', secret) + return Promise.all([users.saveTemp2FASecret(user.id, secret), user, secret, otpauth]) + }) + .then(([_, user, secret, otpauth]) => { return { user_id: user.id, secret, otpauth } }) .catch(err => console.error(err)) @@ -149,6 +156,10 @@ const setup2FA = (username, password, rememberMe, secret, codeConfirmation, cont return authenticateUser(username, password) .then(user => { + if (user.temp_twofa_code !== secret) { + throw new authErrors.InvalidTwoFactorError() + } + initializeSession(context, user, rememberMe) return users.save2FASecret(user.id, secret) }) diff --git a/lib/users.js b/lib/users.js index 0fe7796a..8f58ea00 100644 --- a/lib/users.js +++ b/lib/users.js @@ -64,9 +64,14 @@ function verifyAndUpdateUser (id, ua, ip) { .then(user => user) } +function saveTemp2FASecret (id, secret) { + const sql = 'UPDATE users SET temp_twofa_code=$1 WHERE id=$2' + return db.none(sql, [secret, id]) +} + function save2FASecret (id, secret) { return db.tx(t => { - const q1 = t.none('UPDATE users SET twofa_code=$1 WHERE id=$2', [secret, id]) + const q1 = t.none('UPDATE users SET twofa_code=$1, temp_twofa_code=NULL WHERE id=$2', [secret, id]) const q2 = t.none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id]) return t.batch([q1, q2]) }) @@ -167,6 +172,7 @@ module.exports = { getUserByUsername, verifyAndUpdateUser, updatePassword, + saveTemp2FASecret, save2FASecret, reset2FASecret, validateAuthToken,