From 0be86072f767344bb8ca72ce59867c792491fdbb Mon Sep 17 00:00:00 2001 From: Brian Becker Date: Mon, 23 Dec 2019 15:26:39 -0500 Subject: [PATCH] Add email notification on Two Factor recovery use (#625) * Add email notification on Two Factor recovery use * A user who has lost their 2fa device can clear out the 2fa settings using a recovery code. When this happens it gets logged but no notification to the user occurs. * Add a notification to be sent when 2fa recovery code is used * Add email message templates --- .../Handlebars/RecoverTwoFactor.html.hbs | 20 +++++++++++++++++++ .../Handlebars/RecoverTwoFactor.text.hbs | 8 ++++++++ src/Core/Models/Mail/RecoverTwoFactorModel.cs | 10 ++++++++++ src/Core/Services/IMailService.cs | 1 + .../Implementations/HandlebarsMailService.cs | 17 ++++++++++++++++ .../Services/Implementations/UserService.cs | 1 + .../NoopImplementations/NoopMailService.cs | 5 +++++ 7 files changed, 62 insertions(+) create mode 100644 src/Core/MailTemplates/Handlebars/RecoverTwoFactor.html.hbs create mode 100644 src/Core/MailTemplates/Handlebars/RecoverTwoFactor.text.hbs create mode 100644 src/Core/Models/Mail/RecoverTwoFactorModel.cs diff --git a/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.html.hbs b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.html.hbs new file mode 100644 index 000000000..b2bff8d57 --- /dev/null +++ b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.html.hbs @@ -0,0 +1,20 @@ +{{#>FullHtmlLayout}} + + + + + + + + + + +
+ Your Bitwarden account Two Factor was just reset. +
+ Date: {{TheDate}} at {{TheTime}} {{TimeZone}}
+ IP Address: {{IpAddress}} +
+ If this was not you, you should immediately log in and secure your account. +
+{{/FullHtmlLayout}} diff --git a/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.text.hbs b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.text.hbs new file mode 100644 index 000000000..8e6e75400 --- /dev/null +++ b/src/Core/MailTemplates/Handlebars/RecoverTwoFactor.text.hbs @@ -0,0 +1,8 @@ +{{#>BasicTextLayout}} +Your Bitwarden account Two Factor was just reset. + +Date: {{TheDate}} at {{TheTime}} {{TimeZone}} +IP Address: {{IpAddress}} + +If this was not you, you should immediately log in and secure your account. +{{/BasicTextLayout}} \ No newline at end of file diff --git a/src/Core/Models/Mail/RecoverTwoFactorModel.cs b/src/Core/Models/Mail/RecoverTwoFactorModel.cs new file mode 100644 index 000000000..f9b8cb5d4 --- /dev/null +++ b/src/Core/Models/Mail/RecoverTwoFactorModel.cs @@ -0,0 +1,10 @@ +namespace Bit.Core.Models.Mail +{ + public class RecoverTwoFactorModel : BaseMailModel + { + public string TheDate { get; set; } + public string TheTime { get; set; } + public string TimeZone { get; set; } + public string IpAddress { get; set; } + } +} diff --git a/src/Core/Services/IMailService.cs b/src/Core/Services/IMailService.cs index 42196a0c7..c44d86855 100644 --- a/src/Core/Services/IMailService.cs +++ b/src/Core/Services/IMailService.cs @@ -25,5 +25,6 @@ namespace Bit.Core.Services Task SendPaymentFailedAsync(string email, decimal amount, bool mentionInvoices); Task SendAddedCreditAsync(string email, decimal amount); Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip); + Task SendRecoverTwoFactorEmail(string email, DateTime timestamp, string ip); } } diff --git a/src/Core/Services/Implementations/HandlebarsMailService.cs b/src/Core/Services/Implementations/HandlebarsMailService.cs index 7dc755529..8c7a223ae 100644 --- a/src/Core/Services/Implementations/HandlebarsMailService.cs +++ b/src/Core/Services/Implementations/HandlebarsMailService.cs @@ -283,6 +283,23 @@ namespace Bit.Core.Services await _mailDeliveryService.SendEmailAsync(message); } + public async Task SendRecoverTwoFactorEmail(string email, DateTime timestamp, string ip) + { + var message = CreateDefaultMessage($"Recover 2FA From {ip}", email); + var model = new RecoverTwoFactorModel + { + WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash, + SiteName = _globalSettings.SiteName, + TheDate = timestamp.ToLongDateString(), + TheTime = timestamp.ToShortTimeString(), + TimeZone = "UTC", + IpAddress = ip + }; + await AddMessageContentAsync(message, "RecoverTwoFactor", model); + message.Category = "RecoverTwoFactor"; + await _mailDeliveryService.SendEmailAsync(message); + } + private MailMessage CreateDefaultMessage(string subject, string toEmail) { return CreateDefaultMessage(subject, new List { toEmail }); diff --git a/src/Core/Services/Implementations/UserService.cs b/src/Core/Services/Implementations/UserService.cs index 96bb17d96..5e0885a20 100644 --- a/src/Core/Services/Implementations/UserService.cs +++ b/src/Core/Services/Implementations/UserService.cs @@ -674,6 +674,7 @@ namespace Bit.Core.Services user.TwoFactorProviders = null; user.TwoFactorRecoveryCode = CoreHelpers.SecureRandomString(32, upper: false, special: false); await SaveUserAsync(user); + await _mailService.SendRecoverTwoFactorEmail(user.Email, DateTime.UtcNow, _currentContext.IpAddress); await _eventService.LogUserEventAsync(user.Id, EventType.User_Recovered2fa); return true; diff --git a/src/Core/Services/NoopImplementations/NoopMailService.cs b/src/Core/Services/NoopImplementations/NoopMailService.cs index b20379c1d..5fb3f0c11 100644 --- a/src/Core/Services/NoopImplementations/NoopMailService.cs +++ b/src/Core/Services/NoopImplementations/NoopMailService.cs @@ -87,5 +87,10 @@ namespace Bit.Core.Services { return Task.FromResult(0); } + + public Task SendRecoverTwoFactorEmail(string email, DateTime timestamp, string ip) + { + return Task.FromResult(0); + } } }