Skip to content
Snippets Groups Projects
Unverified Commit 9b9df512 authored by Diego Sampaio's avatar Diego Sampaio
Browse files

Implement 2FA backup codes

parent 590a66a2
No related branches found
No related tags found
No related merge requests found
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
"curly": [2, "all"], "curly": [2, "all"],
"eqeqeq": [2, "allow-null"], "eqeqeq": [2, "allow-null"],
"new-cap": [2, { "new-cap": [2, {
"capIsNewExceptions": ["Match.Optional", "Match.Maybe", "Match.ObjectIncluding", "Push.Configure"] "capIsNewExceptions": ["Match.Optional", "Match.Maybe", "Match.ObjectIncluding", "Push.Configure", "SHA256"]
}], }],
"use-isnan": 2, "use-isnan": 2,
"valid-typeof": 2, "valid-typeof": 2,
......
...@@ -66,6 +66,11 @@ Template.accountSecurity.events({ ...@@ -66,6 +66,11 @@ Template.accountSecurity.events({
Meteor.call('verifyTemp2FAToken', instance.find('#testCode').value, (error, result) => { Meteor.call('verifyTemp2FAToken', instance.find('#testCode').value, (error, result) => {
if (result) { if (result) {
swal({
title: t('Backup_codes'),
text: t('Make_sure_you_have_a_copy_of_your_codes') + '\n' + result.codes.join(' ')
});
instance.find('#testCode').value = ''; instance.find('#testCode').value = '';
instance.state.set(); instance.state.set();
toastr.success(t('Two-factor_authentication_enabled')); toastr.success(t('Two-factor_authentication_enabled'));
......
...@@ -16,7 +16,9 @@ Package.onUse(function(api) { ...@@ -16,7 +16,9 @@ Package.onUse(function(api) {
'accounts-base', 'accounts-base',
'ecmascript', 'ecmascript',
'templating', 'templating',
'rocketchat:lib' 'rocketchat:lib',
'sha',
'random'
]); ]);
api.addFiles('client/accountSecurity.html', 'client'); api.addFiles('client/accountSecurity.html', 'client');
......
...@@ -9,8 +9,7 @@ Meteor.methods({ ...@@ -9,8 +9,7 @@ Meteor.methods({
const user = Meteor.user(); const user = Meteor.user();
if (!user.services || !user.services.totp || !user.services.totp.tempSecret) { if (!user.services || !user.services.totp || !user.services.totp.tempSecret) {
console.error('errour'); throw new Meteor.Error('invalid-totp');
return false;
} }
const verified = speakeasy.totp.verify({ const verified = speakeasy.totp.verify({
...@@ -20,8 +19,17 @@ Meteor.methods({ ...@@ -20,8 +19,17 @@ Meteor.methods({
}); });
if (verified) { if (verified) {
RocketChat.models.Users.enable2FAAndSetSecretByUserId(Meteor.userId(), user.services.totp.tempSecret); // generate 10 backup codes
const codes = [];
const hashedCodes = [];
for (let i = 0; i < 10; i++) {
const code = Random.id(8);
codes.push(code);
hashedCodes.push(SHA256(code));
}
RocketChat.models.Users.enable2FAAndSetSecretAndCodesByUserId(Meteor.userId(), user.services.totp.tempSecret, hashedCodes);
return { codes };
} }
return verified;
} }
}); });
...@@ -11,13 +11,14 @@ RocketChat.models.Users.disable2FAAndSetTempSecretByUserId = function(userId, te ...@@ -11,13 +11,14 @@ RocketChat.models.Users.disable2FAAndSetTempSecretByUserId = function(userId, te
}); });
}; };
RocketChat.models.Users.enable2FAAndSetSecretByUserId = function(userId, secret) { RocketChat.models.Users.enable2FAAndSetSecretAndCodesByUserId = function(userId, secret, backupCodes) {
return this.update({ return this.update({
_id: userId _id: userId
}, { }, {
$set: { $set: {
'services.totp.enabled': true, 'services.totp.enabled': true,
'services.totp.secret': secret 'services.totp.secret': secret,
'services.totp.hashedBackup': backupCodes
}, },
$unset: { $unset: {
'services.totp.tempSecret': 1 'services.totp.tempSecret': 1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment