mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 15:42:48 -05:00
[EC-400] Code clean up Device Verification (#2601)
* EC-400 Clean up code regarding Unknown Device Verification * EC-400 Fix formatting
This commit is contained in:

committed by
GitHub

parent
7594ca1122
commit
69511160cb
@ -62,7 +62,6 @@ public class User : ITableObject<Guid>, ISubscriber, IStorable, IStorableSubscri
|
||||
public bool UsesKeyConnector { get; set; }
|
||||
public int FailedLoginCount { get; set; }
|
||||
public DateTime? LastFailedLoginDate { get; set; }
|
||||
public bool UnknownDeviceVerificationEnabled { get; set; }
|
||||
[MaxLength(7)]
|
||||
public string AvatarColor { get; set; }
|
||||
public DateTime? LastPasswordChangeDate { get; set; }
|
||||
|
@ -1,19 +0,0 @@
|
||||
{{#>FullHtmlLayout}}
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none;" valign="top">
|
||||
Your two-step verification code is: <b style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">{{Token}}</b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none;" valign="top">
|
||||
Use this code to complete logging in with Bitwarden.
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top">
|
||||
This email was sent because you are logging in from a device we don’t recognize. If you did not request this code, you may want to <a target="_blank" clicktracking=off href="https://bitwarden.com/help/master-password/#change-master-password" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #175DDC; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; text-decoration: underline;">change your master password</a>. You can view our tips for selecting a secure master password <a target="_blank" clicktracking=off href="https://bitwarden.com/blog/picking-the-right-password-for-your-password-manager/" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #175DDC; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; text-decoration: underline;">here</a>.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{/FullHtmlLayout}}
|
@ -1,7 +0,0 @@
|
||||
{{#>BasicTextLayout}}
|
||||
Your two-step verification code is: {{Token}}
|
||||
|
||||
Use this code to complete logging in with Bitwarden.
|
||||
|
||||
This email was sent because you are logging in from a device we don’t recognize. If you did not request this code, you may want to change your master password (https://bitwarden.com/help/master-password/#change-master-password). You can view our tips for selecting a secure master password here (https://bitwarden.com/blog/picking-the-right-password-for-your-password-manager/).
|
||||
{{/BasicTextLayout}}
|
@ -13,7 +13,6 @@ public interface IMailService
|
||||
Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail);
|
||||
Task SendChangeEmailEmailAsync(string newEmailAddress, string token);
|
||||
Task SendTwoFactorEmailAsync(string email, string token);
|
||||
Task SendNewDeviceLoginTwoFactorEmailAsync(string email, string token);
|
||||
Task SendNoMasterPasswordHintEmailAsync(string email);
|
||||
Task SendMasterPasswordHintEmailAsync(string email, string hint);
|
||||
Task SendOrganizationInviteEmailAsync(string organizationName, OrganizationUser orgUser, ExpiringToken token);
|
||||
|
@ -19,7 +19,7 @@ public interface IUserService
|
||||
Task<IdentityResult> RegisterUserAsync(User user, string masterPassword, string token, Guid? orgUserId);
|
||||
Task<IdentityResult> RegisterUserAsync(User user);
|
||||
Task SendMasterPasswordHintAsync(string email);
|
||||
Task SendTwoFactorEmailAsync(User user, bool isBecauseNewDeviceLogin = false);
|
||||
Task SendTwoFactorEmailAsync(User user);
|
||||
Task<bool> VerifyTwoFactorEmailAsync(User user, string token);
|
||||
Task<CredentialCreateOptions> StartWebAuthnRegistrationAsync(User user);
|
||||
Task<bool> DeleteWebAuthnKeyAsync(User user, int id);
|
||||
@ -76,6 +76,4 @@ public interface IUserService
|
||||
Task SendOTPAsync(User user);
|
||||
Task<bool> VerifyOTPAsync(User user, string token);
|
||||
Task<bool> VerifySecretAsync(User user, string secret);
|
||||
Task<bool> Needs2FABecauseNewDeviceAsync(User user, string deviceIdentifier, string grantType);
|
||||
bool CanEditDeviceVerificationSettings(User user);
|
||||
}
|
||||
|
@ -323,7 +323,6 @@ public class EmergencyAccessService : IEmergencyAccessService
|
||||
grantor.Key = key;
|
||||
// Disable TwoFactor providers since they will otherwise block logins
|
||||
grantor.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>());
|
||||
grantor.UnknownDeviceVerificationEnabled = false;
|
||||
await _userRepository.ReplaceAsync(grantor);
|
||||
|
||||
// Remove grantor from all organizations unless Owner
|
||||
|
@ -113,21 +113,6 @@ public class HandlebarsMailService : IMailService
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public async Task SendNewDeviceLoginTwoFactorEmailAsync(string email, string token)
|
||||
{
|
||||
var message = CreateDefaultMessage("New Device Login Verification Code", email);
|
||||
var model = new EmailTokenViewModel
|
||||
{
|
||||
Token = token,
|
||||
WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
|
||||
SiteName = _globalSettings.SiteName
|
||||
};
|
||||
await AddMessageContentAsync(message, "NewDeviceLoginTwoFactorEmail", model);
|
||||
message.MetaData.Add("SendGridBypassListManagement", true);
|
||||
message.Category = "TwoFactorEmail";
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public async Task SendMasterPasswordHintEmailAsync(string email, string hint)
|
||||
{
|
||||
var message = CreateDefaultMessage("Your Master Password Hint", email);
|
||||
|
@ -46,7 +46,6 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly IProviderUserRepository _providerUserRepository;
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly IStripeSyncService _stripeSyncService;
|
||||
|
||||
public UserService(
|
||||
@ -77,7 +76,6 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
IGlobalSettings globalSettings,
|
||||
IOrganizationService organizationService,
|
||||
IProviderUserRepository providerUserRepository,
|
||||
IDeviceRepository deviceRepository,
|
||||
IStripeSyncService stripeSyncService)
|
||||
: base(
|
||||
store,
|
||||
@ -113,7 +111,6 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
_globalSettings = globalSettings;
|
||||
_organizationService = organizationService;
|
||||
_providerUserRepository = providerUserRepository;
|
||||
_deviceRepository = deviceRepository;
|
||||
_stripeSyncService = stripeSyncService;
|
||||
}
|
||||
|
||||
@ -353,7 +350,7 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
await _mailService.SendMasterPasswordHintEmailAsync(email, user.MasterPasswordHint);
|
||||
}
|
||||
|
||||
public async Task SendTwoFactorEmailAsync(User user, bool isBecauseNewDeviceLogin = false)
|
||||
public async Task SendTwoFactorEmailAsync(User user)
|
||||
{
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Email);
|
||||
if (provider == null || provider.MetaData == null || !provider.MetaData.ContainsKey("Email"))
|
||||
@ -365,14 +362,7 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
var token = await base.GenerateUserTokenAsync(user, TokenOptions.DefaultEmailProvider,
|
||||
"2faEmail:" + email);
|
||||
|
||||
if (isBecauseNewDeviceLogin)
|
||||
{
|
||||
await _mailService.SendNewDeviceLoginTwoFactorEmailAsync(email, token);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _mailService.SendTwoFactorEmailAsync(email, token);
|
||||
}
|
||||
await _mailService.SendTwoFactorEmailAsync(email, token);
|
||||
}
|
||||
|
||||
public async Task<bool> VerifyTwoFactorEmailAsync(User user, string token)
|
||||
@ -1478,36 +1468,4 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
? await VerifyOTPAsync(user, secret)
|
||||
: await CheckPasswordAsync(user, secret);
|
||||
}
|
||||
|
||||
public async Task<bool> Needs2FABecauseNewDeviceAsync(User user, string deviceIdentifier, string grantType)
|
||||
{
|
||||
return CanEditDeviceVerificationSettings(user)
|
||||
&& user.UnknownDeviceVerificationEnabled
|
||||
&& grantType != "authorization_code"
|
||||
&& await IsNewDeviceAndNotTheFirstOneAsync(user, deviceIdentifier);
|
||||
}
|
||||
|
||||
public bool CanEditDeviceVerificationSettings(User user)
|
||||
{
|
||||
return _globalSettings.TwoFactorAuth.EmailOnNewDeviceLogin
|
||||
&& user.EmailVerified
|
||||
&& !user.UsesKeyConnector
|
||||
&& !(user.GetTwoFactorProviders()?.Any() ?? false);
|
||||
}
|
||||
|
||||
private async Task<bool> IsNewDeviceAndNotTheFirstOneAsync(User user, string deviceIdentifier)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var devices = await _deviceRepository.GetManyByUserIdAsync(user.Id);
|
||||
if (!devices.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !devices.Any(d => d.Identifier == deviceIdentifier);
|
||||
}
|
||||
}
|
||||
|
@ -72,11 +72,6 @@ public class NoopMailService : IMailService
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SendNewDeviceLoginTwoFactorEmailAsync(string email, string token)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SendWelcomeEmailAsync(User user)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
|
@ -73,7 +73,6 @@ public class GlobalSettings : IGlobalSettings
|
||||
public virtual AppleIapSettings AppleIap { get; set; } = new AppleIapSettings();
|
||||
public virtual ISsoSettings Sso { get; set; } = new SsoSettings();
|
||||
public virtual StripeSettings Stripe { get; set; } = new StripeSettings();
|
||||
public virtual ITwoFactorAuthSettings TwoFactorAuth { get; set; } = new TwoFactorAuthSettings();
|
||||
public virtual DistributedIpRateLimitingSettings DistributedIpRateLimiting { get; set; } =
|
||||
new DistributedIpRateLimitingSettings();
|
||||
public virtual IPasswordlessAuthSettings PasswordlessAuth { get; set; } = new PasswordlessAuthSettings();
|
||||
@ -511,11 +510,6 @@ public class GlobalSettings : IGlobalSettings
|
||||
public int MaxNetworkRetries { get; set; } = 2;
|
||||
}
|
||||
|
||||
public class TwoFactorAuthSettings : ITwoFactorAuthSettings
|
||||
{
|
||||
public bool EmailOnNewDeviceLogin { get; set; } = false;
|
||||
}
|
||||
|
||||
public class DistributedIpRateLimitingSettings
|
||||
{
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
@ -13,7 +13,6 @@ public interface IGlobalSettings
|
||||
IFileStorageSettings Attachment { get; set; }
|
||||
IConnectionStringSettings Storage { get; set; }
|
||||
IBaseServiceUriSettings BaseServiceUri { get; set; }
|
||||
ITwoFactorAuthSettings TwoFactorAuth { get; set; }
|
||||
ISsoSettings Sso { get; set; }
|
||||
ILogLevelSettings MinLogLevel { get; set; }
|
||||
IPasswordlessAuthSettings PasswordlessAuth { get; set; }
|
||||
|
@ -1,6 +0,0 @@
|
||||
namespace Bit.Core.Settings;
|
||||
|
||||
public interface ITwoFactorAuthSettings
|
||||
{
|
||||
bool EmailOnNewDeviceLogin { get; set; }
|
||||
}
|
Reference in New Issue
Block a user