1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-05 05:00:19 -05:00
bitwarden/src/Identity/Controllers/AccountsController.cs
Jared Snider 29b47f72ca
Auth/PM-3833 - Remove Deprecated Register and Prelogin endpoints from API (#4206)
* PM-3833 - API - AccountsController.cs && AccountsController.cs - remove prelogin and register endpoints.

* PM-3833 - Move Request and Response models that were used for Prelogin and PostRegister from API to Identity.

* PM-3833 - FIX LINT

* PM-3833 - Fix issues after merge conflict fixes.

* PM-3833 - Another test fix
2024-06-19 15:11:24 -04:00

143 lines
5.6 KiB
C#

using Bit.Core;
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Models.Api.Request.Accounts;
using Bit.Core.Auth.Models.Api.Response.Accounts;
using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Auth.Services;
using Bit.Core.Auth.UserFeatures.Registration;
using Bit.Core.Auth.UserFeatures.WebAuthnLogin;
using Bit.Core.Auth.Utilities;
using Bit.Core.Context;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Data;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Tokens;
using Bit.Core.Tools.Enums;
using Bit.Core.Tools.Models.Business;
using Bit.Core.Tools.Services;
using Bit.Core.Utilities;
using Bit.Identity.Models.Request.Accounts;
using Bit.Identity.Models.Response.Accounts;
using Bit.SharedWeb.Utilities;
using Microsoft.AspNetCore.Mvc;
namespace Bit.Identity.Controllers;
[Route("accounts")]
[ExceptionHandlerFilter]
public class AccountsController : Controller
{
private readonly ICurrentContext _currentContext;
private readonly ILogger<AccountsController> _logger;
private readonly IUserRepository _userRepository;
private readonly IUserService _userService;
private readonly ICaptchaValidationService _captchaValidationService;
private readonly IDataProtectorTokenFactory<WebAuthnLoginAssertionOptionsTokenable> _assertionOptionsDataProtector;
private readonly IGetWebAuthnLoginCredentialAssertionOptionsCommand _getWebAuthnLoginCredentialAssertionOptionsCommand;
private readonly ISendVerificationEmailForRegistrationCommand _sendVerificationEmailForRegistrationCommand;
private readonly IReferenceEventService _referenceEventService;
public AccountsController(
ICurrentContext currentContext,
ILogger<AccountsController> logger,
IUserRepository userRepository,
IUserService userService,
ICaptchaValidationService captchaValidationService,
IDataProtectorTokenFactory<WebAuthnLoginAssertionOptionsTokenable> assertionOptionsDataProtector,
IGetWebAuthnLoginCredentialAssertionOptionsCommand getWebAuthnLoginCredentialAssertionOptionsCommand,
ISendVerificationEmailForRegistrationCommand sendVerificationEmailForRegistrationCommand,
IReferenceEventService referenceEventService
)
{
_currentContext = currentContext;
_logger = logger;
_userRepository = userRepository;
_userService = userService;
_captchaValidationService = captchaValidationService;
_assertionOptionsDataProtector = assertionOptionsDataProtector;
_getWebAuthnLoginCredentialAssertionOptionsCommand = getWebAuthnLoginCredentialAssertionOptionsCommand;
_sendVerificationEmailForRegistrationCommand = sendVerificationEmailForRegistrationCommand;
_referenceEventService = referenceEventService;
}
[HttpPost("register")]
[CaptchaProtected]
public async Task<RegisterResponseModel> PostRegister([FromBody] RegisterRequestModel model)
{
var user = model.ToUser();
var result = await _userService.RegisterUserAsync(user, model.MasterPasswordHash,
model.Token, model.OrganizationUserId);
if (result.Succeeded)
{
var captchaBypassToken = _captchaValidationService.GenerateCaptchaBypassToken(user);
return new RegisterResponseModel(captchaBypassToken);
}
foreach (var error in result.Errors.Where(e => e.Code != "DuplicateUserName"))
{
ModelState.AddModelError(string.Empty, error.Description);
}
await Task.Delay(2000);
throw new BadRequestException(ModelState);
}
[RequireFeature(FeatureFlagKeys.EmailVerification)]
[HttpPost("register/send-verification-email")]
public async Task<IActionResult> PostRegisterSendVerificationEmail([FromBody] RegisterSendVerificationEmailRequestModel model)
{
var token = await _sendVerificationEmailForRegistrationCommand.Run(model.Email, model.Name,
model.ReceiveMarketingEmails);
var refEvent = new ReferenceEvent
{
Type = ReferenceEventType.SignupEmailSubmit,
ClientId = _currentContext.ClientId,
ClientVersion = _currentContext.ClientVersion,
Source = ReferenceEventSource.RegistrationStart
};
await _referenceEventService.RaiseEventAsync(refEvent);
if (token != null)
{
return Ok(token);
}
return NoContent();
}
// Moved from API, If you modify this endpoint, please update API as well. Self hosted installs still use the API endpoints.
[HttpPost("prelogin")]
public async Task<PreloginResponseModel> PostPrelogin([FromBody] PreloginRequestModel model)
{
var kdfInformation = await _userRepository.GetKdfInformationByEmailAsync(model.Email);
if (kdfInformation == null)
{
kdfInformation = new UserKdfInformation
{
Kdf = KdfType.PBKDF2_SHA256,
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
};
}
return new PreloginResponseModel(kdfInformation);
}
[HttpGet("webauthn/assertion-options")]
public WebAuthnLoginAssertionOptionsResponseModel GetWebAuthnLoginAssertionOptions()
{
var options = _getWebAuthnLoginCredentialAssertionOptionsCommand.GetWebAuthnLoginCredentialAssertionOptions();
var tokenable = new WebAuthnLoginAssertionOptionsTokenable(WebAuthnLoginAssertionOptionsScope.Authentication, options);
var token = _assertionOptionsDataProtector.Protect(tokenable);
return new WebAuthnLoginAssertionOptionsResponseModel
{
Options = options,
Token = token
};
}
}