Skip to content

Commit 8beefbb

Browse files
authored
[PM-19685] Remove email delay feature flag (#5622)
* Remove email delay feature flag * Fixed reference. * Removed field from old registration method
1 parent 91fa02f commit 8beefbb

File tree

3 files changed

+7
-32
lines changed

3 files changed

+7
-32
lines changed

src/Core/Auth/UserFeatures/Registration/Implementations/SendVerificationEmailForRegistrationCommand.cs

-18
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,10 @@ public SendVerificationEmailForRegistrationCommand(
5353
var user = await _userRepository.GetByEmailAsync(email);
5454
var userExists = user != null;
5555

56-
// Delays enabled by default; flag must be enabled to remove the delays.
57-
var delaysEnabled = !_featureService.IsEnabled(FeatureFlagKeys.EmailVerificationDisableTimingDelays);
58-
5956
if (!_globalSettings.EnableEmailVerification)
6057
{
61-
6258
if (userExists)
6359
{
64-
65-
if (delaysEnabled)
66-
{
67-
// Add delay to prevent timing attacks
68-
// Note: sub 140 ms feels responsive to users so we are using a random value between 100 - 130 ms
69-
// as it should be long enough to prevent timing attacks but not too long to be noticeable to the user.
70-
await Task.Delay(Random.Shared.Next(100, 130));
71-
}
72-
7360
throw new BadRequestException($"Email {email} is already taken");
7461
}
7562

@@ -87,11 +74,6 @@ public SendVerificationEmailForRegistrationCommand(
8774
await _mailService.SendRegistrationVerificationEmailAsync(email, token);
8875
}
8976

90-
if (delaysEnabled)
91-
{
92-
// Add random delay between 100ms-130ms to prevent timing attacks
93-
await Task.Delay(Random.Shared.Next(100, 130));
94-
}
9577
// User exists but we will return a 200 regardless of whether the email was sent or not; so return null
9678
return null;
9779
}

src/Core/Constants.cs

-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ public static class FeatureFlagKeys
115115
public const string TwoFactorExtensionDataPersistence = "pm-9115-two-factor-extension-data-persistence";
116116
public const string DuoRedirect = "duo-redirect";
117117
public const string EmailVerification = "email-verification";
118-
public const string EmailVerificationDisableTimingDelays = "email-verification-disable-timing-delays";
119118
public const string DeviceTrustLogging = "pm-8285-device-trust-logging";
120119
public const string AuthenticatorTwoFactorToken = "authenticator-2fa-token";
121120
public const string UnauthenticatedExtensionUIRefresh = "unauth-ui-refresh";

src/Identity/Controllers/AccountsController.cs

+7-13
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ public async Task<RegisterResponseModel> PostRegister([FromBody] RegisterRequest
121121
var user = model.ToUser();
122122
var identityResult = await _registerUserCommand.RegisterUserViaOrganizationInviteToken(user, model.MasterPasswordHash,
123123
model.Token, model.OrganizationUserId);
124-
// delaysEnabled false is only for the new registration with email verification process
125-
return await ProcessRegistrationResult(identityResult, user, delaysEnabled: true);
124+
return ProcessRegistrationResult(identityResult, user);
126125
}
127126

128127
[HttpPost("register/send-verification-email")]
@@ -188,7 +187,6 @@ public async Task<RegisterResponseModel> PostRegisterFinish([FromBody] RegisterF
188187
// Users will either have an emailed token or an email verification token - not both.
189188

190189
IdentityResult identityResult = null;
191-
var delaysEnabled = !_featureService.IsEnabled(FeatureFlagKeys.EmailVerificationDisableTimingDelays);
192190

193191
switch (model.GetTokenType())
194192
{
@@ -197,40 +195,40 @@ public async Task<RegisterResponseModel> PostRegisterFinish([FromBody] RegisterF
197195
await _registerUserCommand.RegisterUserViaEmailVerificationToken(user, model.MasterPasswordHash,
198196
model.EmailVerificationToken);
199197

200-
return await ProcessRegistrationResult(identityResult, user, delaysEnabled);
198+
return ProcessRegistrationResult(identityResult, user);
201199
break;
202200
case RegisterFinishTokenType.OrganizationInvite:
203201
identityResult = await _registerUserCommand.RegisterUserViaOrganizationInviteToken(user, model.MasterPasswordHash,
204202
model.OrgInviteToken, model.OrganizationUserId);
205203

206-
return await ProcessRegistrationResult(identityResult, user, delaysEnabled);
204+
return ProcessRegistrationResult(identityResult, user);
207205
break;
208206
case RegisterFinishTokenType.OrgSponsoredFreeFamilyPlan:
209207
identityResult = await _registerUserCommand.RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken(user, model.MasterPasswordHash, model.OrgSponsoredFreeFamilyPlanToken);
210208

211-
return await ProcessRegistrationResult(identityResult, user, delaysEnabled);
209+
return ProcessRegistrationResult(identityResult, user);
212210
break;
213211
case RegisterFinishTokenType.EmergencyAccessInvite:
214212
Debug.Assert(model.AcceptEmergencyAccessId.HasValue);
215213
identityResult = await _registerUserCommand.RegisterUserViaAcceptEmergencyAccessInviteToken(user, model.MasterPasswordHash,
216214
model.AcceptEmergencyAccessInviteToken, model.AcceptEmergencyAccessId.Value);
217215

218-
return await ProcessRegistrationResult(identityResult, user, delaysEnabled);
216+
return ProcessRegistrationResult(identityResult, user);
219217
break;
220218
case RegisterFinishTokenType.ProviderInvite:
221219
Debug.Assert(model.ProviderUserId.HasValue);
222220
identityResult = await _registerUserCommand.RegisterUserViaProviderInviteToken(user, model.MasterPasswordHash,
223221
model.ProviderInviteToken, model.ProviderUserId.Value);
224222

225-
return await ProcessRegistrationResult(identityResult, user, delaysEnabled);
223+
return ProcessRegistrationResult(identityResult, user);
226224
break;
227225

228226
default:
229227
throw new BadRequestException("Invalid registration finish request");
230228
}
231229
}
232230

233-
private async Task<RegisterResponseModel> ProcessRegistrationResult(IdentityResult result, User user, bool delaysEnabled)
231+
private RegisterResponseModel ProcessRegistrationResult(IdentityResult result, User user)
234232
{
235233
if (result.Succeeded)
236234
{
@@ -243,10 +241,6 @@ private async Task<RegisterResponseModel> ProcessRegistrationResult(IdentityResu
243241
ModelState.AddModelError(string.Empty, error.Description);
244242
}
245243

246-
if (delaysEnabled)
247-
{
248-
await Task.Delay(Random.Shared.Next(100, 130));
249-
}
250244
throw new BadRequestException(ModelState);
251245
}
252246

0 commit comments

Comments
 (0)