public async Task <ActionResult> ChangeEmail(ChangeEmailDTO changeEmailDTO) { var userIdC = HttpContext.User.Claims.FirstOrDefault(y => y.Type == ClaimTypes.NameIdentifier); if (userIdC == null || userIdC.Value != changeEmailDTO.UserId) { return(Forbid()); } var user = await userManager.FindByIdAsync(changeEmailDTO.UserId); if (user == null) { return(NotFound()); } if (changeEmailDTO.NewEmail == user.Email) { return(BadRequest("No puedes introducir el mismo email")); } var emailExist = await applicationDbContext.Users.AnyAsync(u => u.NormalizedEmail.ToLower() == changeEmailDTO.NewEmail.ToLower()); if (emailExist) { return(BadRequest("Ese email ya esta en uso")); } var result = await signInManager.CheckPasswordSignInAsync(user, changeEmailDTO.Password, false); if (result.Succeeded) { if (user.EmailConfirmed) { // Send email to change the email await SendChangeEmail(user, changeEmailDTO.NewEmail); return(Ok(new { needConfirm = true })); } else { // previus email is not confirmed string token = await userManager.GenerateChangeEmailTokenAsync(user, changeEmailDTO.NewEmail); var changeResult = await userManager.ChangeEmailAsync(user, changeEmailDTO.NewEmail, token); applicationDbContext.Attach(user); user.EmailConfirmed = false; await applicationDbContext.SaveChangesAsync(); if (changeResult.Succeeded) { await SendEmailConfirmation(user); return(Ok(new { needConfirm = false })); } } } return(BadRequest("Has indicado una contraseña incorrecta")); }
/// <summary> /// This method is used for changing user's email. /// </summary> /// <param name="modelDTO"><see cref="ChangeEmailDTO"/> object.</param> public async Task ChangeEmail(ChangeEmailDTO modelDTO) { if (modelDTO == null) { throw new ValidationException("Model can not be null"); } var user = await Database.UserManager.FindByEmailAsync(modelDTO.OldEmail); if (user == null) { throw new NotFoundException("User was not found", "Email"); } var checkUser = await Database.UserManager.FindByEmailAsync(modelDTO.NewEmail); if (checkUser != null) { throw new ValidationException("User with this email already exists"); } var token = await Database.UserManager.GenerateEmailConfirmationTokenAsync(user); byte[] tokenGeneratedBytes = Encoding.UTF8.GetBytes(token); var tokenEncoded = WebEncoders.Base64UrlEncode(tokenGeneratedBytes); var clientUrl = _appSettings.Client_URL; var url = $@"{clientUrl}/user/confirm-email/?userId={user.Id}&token={tokenEncoded}&newEmail={modelDTO.NewEmail}"; await _emailService.SendEmailAsync(modelDTO.NewEmail, "Смена почты", $"Для изменения почты, перейдя по ссылке: <a href='{url}'>клик</a>."); }
/// <summary> /// This method is used for confirming new email. /// </summary> /// <param name="modelDTO"><see cref="ChangeEmailDTO"/> object.</param> /// <returns>Result of confirming new email.</returns> public async Task <IdentityResult> ConfirmNewEmail(ChangeEmailDTO modelDTO) { var tokenDecodedBytes = WebEncoders.Base64UrlDecode(modelDTO.Token); var tokenDecoded = Encoding.UTF8.GetString(tokenDecodedBytes); if (modelDTO.UserId == null || tokenDecoded == null) { throw new NotFoundException("UserId or token was empty", "Id"); } var user = await Database.UserManager.FindByIdAsync(modelDTO.UserId); if (user == null) { throw new NotFoundException("User was not found", "Id"); } string oldEmail = user.Email; user.EmailConfirmed = false; user.Email = modelDTO.NewEmail; user.NormalizedEmail = modelDTO.NewEmail.ToUpper(); var result = await Database.UserManager.ConfirmEmailAsync(user, tokenDecoded); if (result.Succeeded) { await _emailService.SendEmailAsync(oldEmail, "Смена почты", $"Информируем, что Ваша почта была изменена."); } return(result); }
public async Task <IActionResult> ConfirmEmailChange([FromBody] ChangeEmailDTO changeEmail) { try { if (!ModelState.IsValid) { if (changeEmail.NewEmail != null) { changeEmail.NewEmail = "NEW_EMAIL"; } _logger.LogTrace("Email change failed due to missing parameters.", changeEmail); return(BadRequest("Confirmation details required.")); } var user = await _unitOfWork.UserManager.FindByIdAsync(changeEmail.UserId).ConfigureAwait(false); if (user == null) { _logger.LogWarning("Email change attempted with invalid user details."); return(StatusCode(500, "Email change confirmation unsuccessful.")); } var oldEmail = user.Email; changeEmail.Token = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(changeEmail.Token)); var result = await _unitOfWork.UserManager.ChangeEmailAsync(user, changeEmail.NewEmail, changeEmail.Token).ConfigureAwait(false); if (!result.Succeeded) { return(BadRequest("Email change request failed: validation code invalid.")); } _logger.LogInformation($"{user.UserName} changed their email successfully."); try { user.OldEmail = oldEmail; await RevokeAllActiveUserRefreshCookiesAsync(user).ConfigureAwait(false); _logger.LogInformation($"Active refresh tokens revoked for {user.UserName}."); } catch (InvalidOperationException ex) { _logger.LogError(ex, "Exception thrown attempting to modify refresh tokens in database."); _logger.LogError($"Old email ({oldEmail}) for {user.UserName} may not have updated correctly."); } catch (DbUpdateConcurrencyException ex) { _logger.LogError(ex, "Exception thrown attempting to modify refresh tokens in database."); _logger.LogError($"Old email ({oldEmail}) for {user.UserName} may not have updated correctly."); } InvalidateRefreshCookieInBrowser(); var emailData = new UsernameTemplate() { Username = user.UserName }; var emailResponseOld = await _emailSender .SendEmailAsync(oldEmail, _config["SendGrid:Templates:EmailChanged"], EmailFrom.Account, emailData) .ConfigureAwait(false); if (emailResponseOld.StatusCode != System.Net.HttpStatusCode.Accepted) { _logger.LogError($"SendGrid failed to send email change notification to {user.UserName}'s old email."); } else { _logger.LogInformation($"Email change notification dispatched to {user.UserName}'s old email."); } var emailResponseNew = await _emailSender .SendEmailAsync(changeEmail.NewEmail, _config["SendGrid:Templates:EmailChangeSuccess"], EmailFrom.Account, emailData) .ConfigureAwait(false); if (emailResponseNew.StatusCode != System.Net.HttpStatusCode.Accepted) { _logger.LogError($"SendGrid failed to send email change notification to {user.UserName}'s new email."); } else { _logger.LogInformation($"Email change notification dispatched to {user.UserName}'s new email."); } return(NoContent()); } catch (DbUpdateConcurrencyException ex) { _logger.LogError(ex, "Exception thrown attempting to save new refresh token to database."); return(StatusCode(500, "Email change confirmation unsuccessful.")); } catch (Exception ex) { _logger.LogError(ex, "Exception thrown confirming email change."); return(StatusCode(500, "Email change confirmation unsuccessful.")); } }