From 16e1f2f62201ee6613f40ab08d5a3fc15bfbe75a Mon Sep 17 00:00:00 2001 From: Hudell Date: Thu, 15 Feb 2018 16:16:03 -0200 Subject: [PATCH 1/7] Added Max Delta setting to 2fa --- packages/rocketchat-2fa/server/lib/totp.js | 26 +++++++++++++++---- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + .../rocketchat-lib/server/startup/settings.js | 8 ++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/rocketchat-2fa/server/lib/totp.js b/packages/rocketchat-2fa/server/lib/totp.js index bf81dd043cd04..9fbc7c00f92c3 100644 --- a/packages/rocketchat-2fa/server/lib/totp.js +++ b/packages/rocketchat-2fa/server/lib/totp.js @@ -14,6 +14,7 @@ RocketChat.TOTP = { verify({ secret, token, backupTokens, userId }) { let verified; + let maxDelta = RocketChat.settings.get('Accounts_TwoFactorAuthentication_MaxDelta'); // validates a backup code if (token.length === 8 && backupTokens) { @@ -29,11 +30,26 @@ RocketChat.TOTP = { RocketChat.models.Users.update2FABackupCodesByUserId(userId, backupTokens); } } else { - verified = speakeasy.totp.verify({ - secret, - encoding: 'base32', - token - }); + if (maxDelta) { + let verifiedDelta = speakeasy.totp.verifyDelta({ + secret, + encoding: 'base32', + token, + window: maxDelta + }); + + if (verifiedDelta === undefined) { + verified = false; + } else { + verified = Math.abs(verifiedDelta.delta) < maxDelta; + } + } else { + verified = speakeasy.totp.verify({ + secret, + encoding: 'base32', + token + }); + } } return verified; diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 2211d5673c92b..12fd71535ad20 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -137,6 +137,7 @@ "Accounts_SetDefaultAvatar": "Set Default Avatar", "Accounts_SetDefaultAvatar_Description": "Tries to determine default avatar based on OAuth Account or Gravatar", "Accounts_ShowFormLogin": "Show Form-Based Login", + "Accounts_TwoFactorAuthentication_MaxDelta": "Maximum Delta", "Accounts_UseDefaultBlockedDomainsList": "Use Default Blocked Domains List", "Accounts_UseDNSDomainCheck": "Use DNS Domain Check", "Accounts_UserAddedEmail_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

You may login using your email: [email] and password: [password]. You may be required to change it after your first login.", diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index 2271edd7005c8..d4826a819b37d 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -83,6 +83,14 @@ RocketChat.settings.addGroup('Accounts', function() { public: true }); + this.section('Two Factor Authentication', function(){ + this.add('Accounts_TwoFactorAuthentication_MaxDelta', 0, { + type: 'int', + public: true, + i18nLabel: 'Accounts_TwoFactorAuthentication_MaxDelta' + }); + }); + this.section('Registration', function() { this.add('Accounts_DefaultUsernamePrefixSuggestion', 'user', { type: 'string' From f30239026160266d9bd91b2d8845bc82a3b413e2 Mon Sep 17 00:00:00 2001 From: Hudell Date: Thu, 15 Feb 2018 16:22:25 -0200 Subject: [PATCH 2/7] Removed unnecessary code --- packages/rocketchat-2fa/server/lib/totp.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/rocketchat-2fa/server/lib/totp.js b/packages/rocketchat-2fa/server/lib/totp.js index 9fbc7c00f92c3..80ef84636cb38 100644 --- a/packages/rocketchat-2fa/server/lib/totp.js +++ b/packages/rocketchat-2fa/server/lib/totp.js @@ -38,11 +38,7 @@ RocketChat.TOTP = { window: maxDelta }); - if (verifiedDelta === undefined) { - verified = false; - } else { - verified = Math.abs(verifiedDelta.delta) < maxDelta; - } + verified = verifiedDelta !== undefined; } else { verified = speakeasy.totp.verify({ secret, From bc44d21838f27eb27da98ec8f4beef8e98afdcce Mon Sep 17 00:00:00 2001 From: Hudell Date: Thu, 15 Feb 2018 16:42:11 -0200 Subject: [PATCH 3/7] Organized code --- packages/rocketchat-2fa/server/lib/totp.js | 41 ++++++++++------------ 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/packages/rocketchat-2fa/server/lib/totp.js b/packages/rocketchat-2fa/server/lib/totp.js index 80ef84636cb38..fc00dc8748321 100644 --- a/packages/rocketchat-2fa/server/lib/totp.js +++ b/packages/rocketchat-2fa/server/lib/totp.js @@ -13,42 +13,39 @@ RocketChat.TOTP = { }, verify({ secret, token, backupTokens, userId }) { - let verified; - let maxDelta = RocketChat.settings.get('Accounts_TwoFactorAuthentication_MaxDelta'); - // validates a backup code if (token.length === 8 && backupTokens) { const hashedCode = SHA256(token); const usedCode = backupTokens.indexOf(hashedCode); if (usedCode !== -1) { - verified = true; - backupTokens.splice(usedCode, 1); // mark the code as used (remove it from the list) RocketChat.models.Users.update2FABackupCodesByUserId(userId, backupTokens); + return true; } - } else { - if (maxDelta) { - let verifiedDelta = speakeasy.totp.verifyDelta({ - secret, - encoding: 'base32', - token, - window: maxDelta - }); - verified = verifiedDelta !== undefined; - } else { - verified = speakeasy.totp.verify({ - secret, - encoding: 'base32', - token - }); - } + return false; } - return verified; + const maxDelta = RocketChat.settings.get('Accounts_TwoFactorAuthentication_MaxDelta'); + if (maxDelta) { + const verifiedDelta = speakeasy.totp.verifyDelta({ + secret, + encoding: 'base32', + token, + window: maxDelta + }); + + return verifiedDelta !== undefined; + } + + return speakeasy.totp.verify({ + secret, + encoding: 'base32', + token + }); }, generateCodes() { From 1705451667e26c4d9f6b34224f8beabbde93c8af Mon Sep 17 00:00:00 2001 From: Hudell Date: Thu, 15 Feb 2018 16:43:39 -0200 Subject: [PATCH 4/7] Added missing space --- packages/rocketchat-lib/server/startup/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index d4826a819b37d..ea363bf8e3fc8 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -83,7 +83,7 @@ RocketChat.settings.addGroup('Accounts', function() { public: true }); - this.section('Two Factor Authentication', function(){ + this.section('Two Factor Authentication', function() { this.add('Accounts_TwoFactorAuthentication_MaxDelta', 0, { type: 'int', public: true, From 6772dc65331bdf8b8be745f39c06b769e7ad0255 Mon Sep 17 00:00:00 2001 From: Hudell Date: Thu, 15 Feb 2018 16:53:02 -0200 Subject: [PATCH 5/7] Removed trailing spaces --- packages/rocketchat-2fa/server/lib/totp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-2fa/server/lib/totp.js b/packages/rocketchat-2fa/server/lib/totp.js index fc00dc8748321..54b4f579f2de8 100644 --- a/packages/rocketchat-2fa/server/lib/totp.js +++ b/packages/rocketchat-2fa/server/lib/totp.js @@ -40,7 +40,7 @@ RocketChat.TOTP = { return verifiedDelta !== undefined; } - + return speakeasy.totp.verify({ secret, encoding: 'base32', From d813f2a329cd1cd7c5939838cf9e19ece5756b87 Mon Sep 17 00:00:00 2001 From: Hudell Date: Thu, 15 Feb 2018 17:59:06 -0200 Subject: [PATCH 6/7] Added Description explaining the Max Delta --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 12fd71535ad20..0b24f709d9a80 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -138,6 +138,7 @@ "Accounts_SetDefaultAvatar_Description": "Tries to determine default avatar based on OAuth Account or Gravatar", "Accounts_ShowFormLogin": "Show Form-Based Login", "Accounts_TwoFactorAuthentication_MaxDelta": "Maximum Delta", + "Accounts_TwoFactorAuthentication_MaxDelta_Description": "The Maximum Delta determines how many tokens are valid at any given time. Tokens are generated every 30 seconds, and are valid for (30 * Maximum Delta) seconds.
Example: With a Maximum Delta set to 10, each token can be used up to 300 seconds before or after it's timestamp. This is useful when the client's clock is not properly synced with the server.", "Accounts_UseDefaultBlockedDomainsList": "Use Default Blocked Domains List", "Accounts_UseDNSDomainCheck": "Use DNS Domain Check", "Accounts_UserAddedEmail_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

You may login using your email: [email] and password: [password]. You may be required to change it after your first login.", From 8aa10df758f6cbceea8d23f362722914ce71199c Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Wed, 7 Mar 2018 14:18:15 -0300 Subject: [PATCH 7/7] Set 2FA delta default to 1 --- packages/rocketchat-lib/server/startup/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index 43137bb5d7613..643610aeb7375 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -84,7 +84,7 @@ RocketChat.settings.addGroup('Accounts', function() { }); this.section('Two Factor Authentication', function() { - this.add('Accounts_TwoFactorAuthentication_MaxDelta', 0, { + this.add('Accounts_TwoFactorAuthentication_MaxDelta', 1, { type: 'int', public: true, i18nLabel: 'Accounts_TwoFactorAuthentication_MaxDelta'