From 89c516f8e2ea0703447660b2e677e720f52cb67c Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Sun, 30 Mar 2025 13:53:52 -0400 Subject: [PATCH] Remove email delay feature flag --- ...ndVerificationEmailForRegistrationCommand.cs | 13 ------------- src/Core/Constants.cs | 5 ++--- src/Identity/Controllers/AccountsController.cs | 17 ++++++----------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/Core/Auth/UserFeatures/Registration/Implementations/SendVerificationEmailForRegistrationCommand.cs b/src/Core/Auth/UserFeatures/Registration/Implementations/SendVerificationEmailForRegistrationCommand.cs index 21a421b9d0..377f848751 100644 --- a/src/Core/Auth/UserFeatures/Registration/Implementations/SendVerificationEmailForRegistrationCommand.cs +++ b/src/Core/Auth/UserFeatures/Registration/Implementations/SendVerificationEmailForRegistrationCommand.cs @@ -53,23 +53,10 @@ public class SendVerificationEmailForRegistrationCommand : ISendVerificationEmai var user = await _userRepository.GetByEmailAsync(email); var userExists = user != null; - // Delays enabled by default; flag must be enabled to remove the delays. - var delaysEnabled = !_featureService.IsEnabled(FeatureFlagKeys.EmailVerificationDisableTimingDelays); - if (!_globalSettings.EnableEmailVerification) { - if (userExists) { - - if (delaysEnabled) - { - // Add delay to prevent timing attacks - // Note: sub 140 ms feels responsive to users so we are using a random value between 100 - 130 ms - // as it should be long enough to prevent timing attacks but not too long to be noticeable to the user. - await Task.Delay(Random.Shared.Next(100, 130)); - } - throw new BadRequestException($"Email {email} is already taken"); } diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 028ee2042b..3ba71ce649 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -114,7 +114,6 @@ public static class FeatureFlagKeys public const string PM9112DeviceApprovalPersistence = "pm-9112-device-approval-persistence"; public const string DuoRedirect = "duo-redirect"; public const string EmailVerification = "email-verification"; - public const string EmailVerificationDisableTimingDelays = "email-verification-disable-timing-delays"; public const string DeviceTrustLogging = "pm-8285-device-trust-logging"; public const string AuthenticatorTwoFactorToken = "authenticator-2fa-token"; public const string IdpAutoSubmitLogin = "idp-auto-submit-login"; @@ -154,7 +153,7 @@ public static class FeatureFlagKeys public const string PrivateKeyRegeneration = "pm-12241-private-key-regeneration"; public const string Argon2Default = "argon2-default"; public const string UserkeyRotationV2 = "userkey-rotation-v2"; - + /* Mobile Team */ public const string NativeCarouselFlow = "native-carousel-flow"; public const string NativeCreateAccountFlow = "native-create-account-flow"; @@ -192,7 +191,7 @@ public static class FeatureFlagKeys public const string RestrictProviderAccess = "restrict-provider-access"; public const string SecurityTasks = "security-tasks"; public const string SSHKeyItemVaultItem = "ssh-key-vault-item"; - public const string CipherKeyEncryption = "cipher-key-encryption"; + public const string CipherKeyEncryption = "cipher-key-encryption"; public static List GetAllKeys() { diff --git a/src/Identity/Controllers/AccountsController.cs b/src/Identity/Controllers/AccountsController.cs index c840a7ddc5..27b8d66b90 100644 --- a/src/Identity/Controllers/AccountsController.cs +++ b/src/Identity/Controllers/AccountsController.cs @@ -188,7 +188,6 @@ public class AccountsController : Controller // Users will either have an emailed token or an email verification token - not both. IdentityResult identityResult = null; - var delaysEnabled = !_featureService.IsEnabled(FeatureFlagKeys.EmailVerificationDisableTimingDelays); switch (model.GetTokenType()) { @@ -197,32 +196,32 @@ public class AccountsController : Controller await _registerUserCommand.RegisterUserViaEmailVerificationToken(user, model.MasterPasswordHash, model.EmailVerificationToken); - return await ProcessRegistrationResult(identityResult, user, delaysEnabled); + return ProcessRegistrationResult(identityResult, user); break; case RegisterFinishTokenType.OrganizationInvite: identityResult = await _registerUserCommand.RegisterUserViaOrganizationInviteToken(user, model.MasterPasswordHash, model.OrgInviteToken, model.OrganizationUserId); - return await ProcessRegistrationResult(identityResult, user, delaysEnabled); + return ProcessRegistrationResult(identityResult, user); break; case RegisterFinishTokenType.OrgSponsoredFreeFamilyPlan: identityResult = await _registerUserCommand.RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken(user, model.MasterPasswordHash, model.OrgSponsoredFreeFamilyPlanToken); - return await ProcessRegistrationResult(identityResult, user, delaysEnabled); + return ProcessRegistrationResult(identityResult, user); break; case RegisterFinishTokenType.EmergencyAccessInvite: Debug.Assert(model.AcceptEmergencyAccessId.HasValue); identityResult = await _registerUserCommand.RegisterUserViaAcceptEmergencyAccessInviteToken(user, model.MasterPasswordHash, model.AcceptEmergencyAccessInviteToken, model.AcceptEmergencyAccessId.Value); - return await ProcessRegistrationResult(identityResult, user, delaysEnabled); + return ProcessRegistrationResult(identityResult, user); break; case RegisterFinishTokenType.ProviderInvite: Debug.Assert(model.ProviderUserId.HasValue); identityResult = await _registerUserCommand.RegisterUserViaProviderInviteToken(user, model.MasterPasswordHash, model.ProviderInviteToken, model.ProviderUserId.Value); - return await ProcessRegistrationResult(identityResult, user, delaysEnabled); + return ProcessRegistrationResult(identityResult, user); break; default: @@ -230,7 +229,7 @@ public class AccountsController : Controller } } - private async Task ProcessRegistrationResult(IdentityResult result, User user, bool delaysEnabled) + private RegisterResponseModel ProcessRegistrationResult(IdentityResult result, User user) { if (result.Succeeded) { @@ -243,10 +242,6 @@ public class AccountsController : Controller ModelState.AddModelError(string.Empty, error.Description); } - if (delaysEnabled) - { - await Task.Delay(Random.Shared.Next(100, 130)); - } throw new BadRequestException(ModelState); }