1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 16:42:50 -05:00

Auth/PM-6198 - Registration with Email Verification - Add email clicked endpoint (#4520)

* PM-6198 - RegistrationEmailVerificationTokenable - add new static validate token method

* PM-6198 - Rename RegistrationStart to Registration as we now have to add another anonymous reference event.

* PM-6198 - rest of work

* PM-6198 - Unit test new account controller method.

* PM-6198 - Integration test new account controller endpoint
This commit is contained in:
Jared Snider
2024-07-22 17:24:42 -04:00
committed by GitHub
parent 45b99336da
commit 1b5f9e3f3e
9 changed files with 229 additions and 6 deletions

View File

@ -41,6 +41,7 @@ public class AccountsController : Controller
private readonly ISendVerificationEmailForRegistrationCommand _sendVerificationEmailForRegistrationCommand;
private readonly IReferenceEventService _referenceEventService;
private readonly IFeatureService _featureService;
private readonly IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> _registrationEmailVerificationTokenDataFactory;
public AccountsController(
ICurrentContext currentContext,
@ -52,7 +53,8 @@ public class AccountsController : Controller
IGetWebAuthnLoginCredentialAssertionOptionsCommand getWebAuthnLoginCredentialAssertionOptionsCommand,
ISendVerificationEmailForRegistrationCommand sendVerificationEmailForRegistrationCommand,
IReferenceEventService referenceEventService,
IFeatureService featureService
IFeatureService featureService,
IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> registrationEmailVerificationTokenDataFactory
)
{
_currentContext = currentContext;
@ -65,6 +67,7 @@ public class AccountsController : Controller
_sendVerificationEmailForRegistrationCommand = sendVerificationEmailForRegistrationCommand;
_referenceEventService = referenceEventService;
_featureService = featureService;
_registrationEmailVerificationTokenDataFactory = registrationEmailVerificationTokenDataFactory;
}
[HttpPost("register")]
@ -90,7 +93,7 @@ public class AccountsController : Controller
Type = ReferenceEventType.SignupEmailSubmit,
ClientId = _currentContext.ClientId,
ClientVersion = _currentContext.ClientVersion,
Source = ReferenceEventSource.RegistrationStart
Source = ReferenceEventSource.Registration
};
await _referenceEventService.RaiseEventAsync(refEvent);
@ -102,6 +105,39 @@ public class AccountsController : Controller
return NoContent();
}
[RequireFeature(FeatureFlagKeys.EmailVerification)]
[HttpPost("register/verification-email-clicked")]
public async Task<IActionResult> PostRegisterVerificationEmailClicked([FromBody] RegisterVerificationEmailClickedRequestModel model)
{
var tokenValid = RegistrationEmailVerificationTokenable.ValidateToken(_registrationEmailVerificationTokenDataFactory, model.EmailVerificationToken, model.Email);
// Check to see if the user already exists - this is just to catch the unlikely but possible case
// where a user finishes registration and then clicks the email verification link again.
var user = await _userRepository.GetByEmailAsync(model.Email);
var userExists = user != null;
var refEvent = new ReferenceEvent
{
Type = ReferenceEventType.SignupEmailClicked,
ClientId = _currentContext.ClientId,
ClientVersion = _currentContext.ClientVersion,
Source = ReferenceEventSource.Registration,
EmailVerificationTokenValid = tokenValid,
UserAlreadyExists = userExists
};
await _referenceEventService.RaiseEventAsync(refEvent);
if (!tokenValid || userExists)
{
throw new BadRequestException("Expired link. Please restart registration or try logging in. You may already have an account");
}
return Ok();
}
[RequireFeature(FeatureFlagKeys.EmailVerification)]
[HttpPost("register/finish")]
public async Task<RegisterResponseModel> PostRegisterFinish([FromBody] RegisterFinishRequestModel model)