Exemplo n.º 1
0
        public async Task <IActionResult> SubmitTokenInput(TokenInputViewModel model)
        {
            if (!ModelState.IsValid ||
                String.IsNullOrWhiteSpace(model.Email) ||
                String.IsNullOrWhiteSpace(model.Purpose) ||
                String.IsNullOrWhiteSpace(model.Token))
            {
                return(View(model));
            }

            var email = _userManager.NormalizeKey(model.Email);

            model.Token = model.Token.Replace(" ", "");

            var userWithConfirmedEmail = await _userManager.FindByLoginAsync("Email", email);

            var userCurrentlySignedIn = await _userManager.GetUserAsync(User);

            var userEmpty = new ApplicationUser()
            {
                Id            = email,
                Email         = email,
                SecurityStamp = TemporarySecurityStamp
            };

            var isTokenValid = false;

            if (model.Purpose == "RegisterOrLogin") // Trying to register or login
            {
                await _signInManager.SignOutAsync();

                isTokenValid = await _userManager.VerifyUserTokenAsync(
                    userWithConfirmedEmail  // Case: logging-in
                    ?? userEmpty,           // Case: registering,
                    "Email", model.Purpose, model.Token);
            }
            else // Trying to add email
            {
                if (userCurrentlySignedIn == null) // If the user is not signed in, prompt them to, with the return url leading back here
                {
                    return(RedirectToAction(nameof(Login), new
                    {
                        returnUrl = Request.Path + Request.QueryString
                    }));
                }

                isTokenValid = await _userManager.VerifyUserTokenAsync(
                    userCurrentlySignedIn,
                    "Email", model.Purpose, model.Token);
            }

            if (!isTokenValid)
            {
                _notice.AddErrors(ModelState, "Error validating code, it might have expired. Please try again!");
                return(View(model));
            }

            // Invalidates all tokens for user when trying to login or add login
            // Note: this also invalidates any attempts to add more logins than allowed
            if ((userCurrentlySignedIn ?? userWithConfirmedEmail) != null)
            {
                var updateSecStampResult = await _userManager.UpdateSecurityStampAsync(userCurrentlySignedIn ?? userWithConfirmedEmail);

                if (!updateSecStampResult.Succeeded)
                {
                    _notice.AddErrors(ModelState);
                    return(View(model));
                }
            }

            // Valid {token + email (user) + purpose} supplied

            if (model.Purpose == "RegisterOrLogin") // Trying to register or login
            {
                if (userWithConfirmedEmail == null) // Success trying to register
                {
                    var token = await _userManager.GenerateUserTokenAsync(userEmpty, "Default", "Register");

                    return(View(nameof(Register), new RegisterViewModel
                    {
                        RememberMe = model.RememberMe,
                        Email = email,
                        UserName = GenerateUserName(email),
                        Token = token,
                        ReturnUrl = model.ReturnUrl
                    }));
                }
                else // Success trying to login
                {
                    await _events.AddEvent(AuthEventType.Login, JsonConvert.SerializeObject(new
                    {
                        LoginProvider = "Email",
                        ProviderKey   = model.Email
                    }), userWithConfirmedEmail);

                    await _signInManager.SignInAsync(userWithConfirmedEmail, isPersistent : model.RememberMe);
                }
            }
            else // Trying to add email
            {
                var userWithConfirmedEmailToAdd = await _userManager.FindByLoginAsync("Email", email);

                if (userWithConfirmedEmailToAdd == null) // Email to be added never seen before, add email to userCurrentlySignedIn
                {
                    var addLoginResult = await _userManager.AddLoginAsync(userCurrentlySignedIn,
                                                                          new UserLoginInfo("Email", email, "Email"));

                    if (!addLoginResult.Succeeded)
                    {
                        _notice.AddErrors(ModelState, addLoginResult);
                        return(View(model));
                    }

                    userCurrentlySignedIn.Email          = email;
                    userCurrentlySignedIn.EmailConfirmed = true;
                    var updateUserResult = await _userManager.UpdateAsync(userCurrentlySignedIn);

                    if (!updateUserResult.Succeeded)
                    {
                        _notice.AddErrors(ModelState, updateUserResult);
                        return(View(model));
                    }

                    await _events.AddEvent(AuthEventType.AddLogin, JsonConvert.SerializeObject(new
                    {
                        LoginProvider = "Email",
                        ProviderKey   = model.Email
                    }), userCurrentlySignedIn);
                }
                else // Email to be added is in use
                {
                    // Note: this area is unlikely to be reached since security stamp is changed once a login is added
                    if (userWithConfirmedEmailToAdd.Id == userCurrentlySignedIn.Id) // Email is already in user's account
                    {
                        _notice.AddErrors(ModelState, "This email is already in your account.");
                        return(View(model));
                    }
                    else // Email associated with another account (same user since both verified!)
                    {
                        _notice.AddErrors(ModelState, "This email is in another user's account. Try logging in using that email instead.");
                        return(View(model));
                    }
                }
            }

            // Success
            return(RedirectToLocal(model.ReturnUrl));
        }
Exemplo n.º 2
0
 public static string TokenInputLink(this IUrlHelper urlHelper, string scheme, TokenInputViewModel tokenModel)
 {
     return(urlHelper.Action(
                action: nameof(AccountController.TokenInput),
                controller: "Account",
                values: tokenModel,
                protocol: scheme));
 }
Exemplo n.º 3
0
 public IActionResult TokenInput(TokenInputViewModel model)
 {
     return(View(model));
 }