Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security Patches #1624

Merged
merged 3 commits into from
Oct 31, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 37 additions & 11 deletions API/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public async Task<ActionResult<UserDto>> Login(LoginDto loginDto)
.Include(u => u.UserPreferences)
.SingleOrDefaultAsync(x => x.NormalizedUserName == loginDto.Username.ToUpper());

if (user == null) return Unauthorized("Invalid username");
if (user == null) return Unauthorized("Your credentials are not correct");

var result = await _signInManager
.CheckPasswordSignInAsync(user, loginDto.Password, true);
Expand All @@ -198,7 +198,7 @@ public async Task<ActionResult<UserDto>> Login(LoginDto loginDto)

if (!result.Succeeded)
{
return Unauthorized(result.IsNotAllowed ? "You must confirm your email first" : "Your credentials are not correct.");
return Unauthorized(result.IsNotAllowed ? "You must confirm your email first" : "Your credentials are not correct");
}

// Update LastActive on account
Expand Down Expand Up @@ -632,6 +632,11 @@ await _emailService.SendConfirmationEmail(new ConfirmationEmailDto()
return BadRequest("There was an error setting up your account. Please check the logs");
}

/// <summary>
/// Last step in authentication flow, confirms the email token for email
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost("confirm-email")]
public async Task<ActionResult<UserDto>> ConfirmEmail(ConfirmEmailDto dto)
Expand All @@ -640,7 +645,8 @@ public async Task<ActionResult<UserDto>> ConfirmEmail(ConfirmEmailDto dto)

if (user == null)
{
return BadRequest("The email does not match the registered email");
_logger.LogInformation("confirm-email failed from invalid registered email: {Email}", dto.Email);
return BadRequest("Invalid email confirmation");
}

// Validate Password and Username
Expand All @@ -654,7 +660,11 @@ public async Task<ActionResult<UserDto>> ConfirmEmail(ConfirmEmailDto dto)
}


if (!await ConfirmEmailToken(dto.Token, user)) return BadRequest("Invalid Email Token");
if (!await ConfirmEmailToken(dto.Token, user))
{
_logger.LogInformation("confirm-email failed from invalid token: {Token}", dto.Token);
return BadRequest("Invalid email confirmation");
}

user.UserName = dto.Username;
user.ConfirmationToken = null;
Expand Down Expand Up @@ -694,11 +704,15 @@ public async Task<ActionResult> ConfirmEmailUpdate(ConfirmEmailUpdateDto dto)
var user = await _unitOfWork.UserRepository.GetUserByConfirmationToken(dto.Token);
if (user == null)
{
return BadRequest("Invalid Email Token");
_logger.LogInformation("confirm-email failed from invalid registered email: {Email}", dto.Email);
return BadRequest("Invalid email confirmation");
}

if (!await ConfirmEmailToken(dto.Token, user)) return BadRequest("Invalid Email Token");

if (!await ConfirmEmailToken(dto.Token, user))
{
_logger.LogInformation("confirm-email failed from invalid token: {Token}", dto.Token);
return BadRequest("Invalid email confirmation");
}

_logger.LogInformation("User is updating email from {OldEmail} to {NewEmail}", user.Email, dto.Email);
var result = await _userManager.SetEmailAsync(user, dto.Email);
Expand Down Expand Up @@ -728,12 +742,16 @@ public async Task<ActionResult<string>> ConfirmForgotPassword(ConfirmPasswordRes
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
if (user == null)
{
return BadRequest("Invalid Details");
return BadRequest("Invalid credentials");
}

var result = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider,
"ResetPassword", dto.Token);
if (!result) return BadRequest("Unable to reset password, your email token is not correct.");
if (!result)
{
_logger.LogInformation("Unable to reset password, your email token is not correct: {@Dto}", dto);
return BadRequest("Invalid credentials");
}

var errors = await _accountService.ChangeUserPassword(user, dto.Password);
return errors.Any() ? BadRequest(errors) : Ok("Password updated");
Expand Down Expand Up @@ -801,9 +819,13 @@ public async Task<ActionResult<bool>> IsEmailConfirmed()
public async Task<ActionResult<UserDto>> ConfirmMigrationEmail(ConfirmMigrationEmailDto dto)
{
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
if (user == null) return BadRequest("This email is not on system");
if (user == null) return BadRequest("Invalid credentials");

if (!await ConfirmEmailToken(dto.Token, user)) return BadRequest("Invalid Email Token");
if (!await ConfirmEmailToken(dto.Token, user))
{
_logger.LogInformation("confirm-migration-email email token is invalid");
return BadRequest("Invalid credentials");
}

await _unitOfWork.CommitAsync();

Expand Down Expand Up @@ -865,6 +887,10 @@ private string GenerateEmailLink(string token, string routePart, string email, b
[HttpPost("migrate-email")]
public async Task<ActionResult<string>> MigrateEmail(MigrateUserEmailDto dto)
{
// If there is an admin account already, return
var users = await _unitOfWork.UserRepository.GetAdminUsersAsync();
if (users.Any()) return BadRequest("Admin already exists");

// Check if there is an existing invite
var emailValidationErrors = await _accountService.ValidateEmail(dto.Email);
if (emailValidationErrors.Any())
Expand Down