1
0
mirror of https://github.com/bitwarden/server synced 2025-12-28 14:13:48 +00:00

[PM-24211]: 2FA Send Email Login validation should use AuthRequest.IsValidForAuthentication (#6695)

* fix(two-factor-controller) [PM-24211]: Update send email validation to use auth request's IsValidForAuthentication.

* refactor(login-features) [PM-24211]: Remove Core.LoginFeatures as no longer used; AuthRequest.IsValidForAuthentication should be used for any applicable use cases.

* feat(auth-request) [PM-24211]: Add tests for AuthRequest.IsValidForAuthentication.

* fix(two-factor-controller) [PM-24211]: Branching logic should return on successful send.

* chore(auth-request) [PM-24211]: Remove some old comments (solved-for).

* fix(two-factor-controller) [PM-24211]: Update some comments (clarification/naming).

* fix(two-factor-controller) [PM-24211]: Rephrase a comment (accuracy).
This commit is contained in:
Dave
2025-12-09 09:30:06 -05:00
committed by GitHub
parent d26b5fa029
commit d1ae1fffd6
7 changed files with 232 additions and 57 deletions

View File

@@ -9,7 +9,6 @@ using Bit.Api.Models.Response;
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Identity;
using Bit.Core.Auth.Identity.TokenProviders;
using Bit.Core.Auth.LoginFeatures.PasswordlessLogin.Interfaces;
using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Auth.Services;
using Bit.Core.Context;
@@ -35,7 +34,7 @@ public class TwoFactorController : Controller
private readonly IOrganizationService _organizationService;
private readonly UserManager<User> _userManager;
private readonly ICurrentContext _currentContext;
private readonly IVerifyAuthRequestCommand _verifyAuthRequestCommand;
private readonly IAuthRequestRepository _authRequestRepository;
private readonly IDuoUniversalTokenService _duoUniversalTokenService;
private readonly IDataProtectorTokenFactory<TwoFactorAuthenticatorUserVerificationTokenable> _twoFactorAuthenticatorDataProtector;
private readonly IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> _ssoEmailTwoFactorSessionDataProtector;
@@ -47,7 +46,7 @@ public class TwoFactorController : Controller
IOrganizationService organizationService,
UserManager<User> userManager,
ICurrentContext currentContext,
IVerifyAuthRequestCommand verifyAuthRequestCommand,
IAuthRequestRepository authRequestRepository,
IDuoUniversalTokenService duoUniversalConfigService,
IDataProtectorTokenFactory<TwoFactorAuthenticatorUserVerificationTokenable> twoFactorAuthenticatorDataProtector,
IDataProtectorTokenFactory<SsoEmail2faSessionTokenable> ssoEmailTwoFactorSessionDataProtector,
@@ -58,7 +57,7 @@ public class TwoFactorController : Controller
_organizationService = organizationService;
_userManager = userManager;
_currentContext = currentContext;
_verifyAuthRequestCommand = verifyAuthRequestCommand;
_authRequestRepository = authRequestRepository;
_duoUniversalTokenService = duoUniversalConfigService;
_twoFactorAuthenticatorDataProtector = twoFactorAuthenticatorDataProtector;
_ssoEmailTwoFactorSessionDataProtector = ssoEmailTwoFactorSessionDataProtector;
@@ -350,14 +349,15 @@ public class TwoFactorController : Controller
if (user != null)
{
// Check if 2FA email is from Passwordless.
// Check if 2FA email is from a device approval ("Log in with device") scenario.
if (!string.IsNullOrEmpty(requestModel.AuthRequestAccessCode))
{
if (await _verifyAuthRequestCommand
.VerifyAuthRequestAsync(new Guid(requestModel.AuthRequestId),
requestModel.AuthRequestAccessCode))
var authRequest = await _authRequestRepository.GetByIdAsync(new Guid(requestModel.AuthRequestId));
if (authRequest != null &&
authRequest.IsValidForAuthentication(user.Id, requestModel.AuthRequestAccessCode))
{
await _twoFactorEmailService.SendTwoFactorEmailAsync(user);
return;
}
}
else if (!string.IsNullOrEmpty(requestModel.SsoEmail2FaSessionToken))