Example #1
0
        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);
        }
Example #4
0
        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."));
            }
        }