public async Task <IActionResult> ExternalLoginCallback(ExternalLoginCallbackViewModel model)
        {
            if (!ModelState.IsValid)
            {
                throw new ValidationException(ModelState.GetValidationString());
            }

            if (model.RemoteError != null)
            {
                string error = $"Error from external login: {model.RemoteError}";
                logger.LogError(error);
                return(Redirect($"{model.ErrorUrl}?error=external-login&message={WebUtility.UrlEncode(error)}&returnUrl={model.ReturnUrl}"));
            }

            ExternalLoginInfo?info = await signInManager.GetExternalLoginInfoAsync().ConfigureAwait(false);

            if (info == null)
            {
                string error = $"Error from external login: unable to retrieve user data";
                logger.LogError(error);
                return(Redirect($"{model.ErrorUrl}?error=external-userdata&message={WebUtility.UrlEncode(error)}&returnUrl={model.ReturnUrl}"));
            }

            // Sign in the user with this external login provider if the user already has a login.
            SignInResult result = await signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent : false).ConfigureAwait(false);

            if (result.Succeeded)
            {
                logger.LogInformation("User logged in with {0} provider.", info.LoginProvider);
                return(Redirect(model.ReturnUrl));
            }
            else if (result.IsLockedOut)
            {
                logger.LogInformation("User is locked out");
                return(Redirect($"{model.ErrorUrl}?error=lockout&message={WebUtility.UrlEncode("User is locked out")}&returnUrl={model.ReturnUrl}"));
            }

            // If the user can't login with the external login, create a new account or link one
            string             email         = info.Principal.FindFirstValue(ClaimTypes.Email);
            ExternalUserResult newUserResult = await userService.CreateOrAddExternalToUser(email, info).ConfigureAwait(false);

            if (newUserResult.Result.Succeeded)
            {
                if (newUserResult.AddedUser)
                {
                    return(Redirect(model.FinishRegistrationUrl));
                }
                else
                {
                    return(Redirect(model.ReturnUrl));
                }
            }
            else
            {
                string error = string.Join(", ", newUserResult.Result.Errors.Select(e => e.Description));
                logger.LogError(error);
                return(Redirect($"{model.ErrorUrl}?error=external-login-create&message={WebUtility.UrlEncode(error)}&returnUrl={model.ReturnUrl}"));
            }
        }
Exemplo n.º 2
0
        public async Task <ExternalUserResult> CreateOrAddExternalToUser(string email, ExternalLoginInfo info)
        {
            ApplicationUser?user = await userManager.FindByEmailAsync(email).ConfigureAwait(false);

            if (user != null)
            {
                if (await userManager.IsInRoleAsync(user, AuthorizationConstants.AdminRole).ConfigureAwait(false))
                {
                    // Don't link accounts for admin users, security issue..
                    logger.LogError("Attempt to link accounts for admin user: {0}, {1}", email, info.LoginProvider);
                    throw new InvalidOperationException("Attempted to link account for admin user");
                }
                IdentityResult result = await userManager.AddLoginAsync(user, info).ConfigureAwait(false);

                var externalResult = new ExternalUserResult(user, result, info, false);

                if (result.Succeeded)
                {
                    logger.LogInformation("Added external login to account: {0}, {1}", email, info.LoginProvider);
                    await emailSender.SendEmailTemplated(user.Email, "Account Linked", "AccountLinked", externalResult).ConfigureAwait(false);
                }
                else
                {
                    LogErrors("Adding external login", result);
                }

                return(externalResult);
            }
            else
            {
                logger.LogInformation("Creating user from external login");
                user = new ApplicationUser(email: email, registrationDate: DateTime.UtcNow);
                IdentityResult result = await userManager.CreateAsync(user).ConfigureAwait(false);

                if (result.Succeeded)
                {
                    result = await userManager.AddLoginAsync(user, info).ConfigureAwait(false);

                    if (!result.Succeeded)
                    {
                        LogErrors("Adding external login", result);
                    }
                    else
                    {
                        await emailSender.SendEmailTemplated(user.Email, "Account Creation", "UserCreated").ConfigureAwait(false);

                        logger.LogInformation("Created user from external login");
                    }

                    return(new ExternalUserResult(user, result, info, true));
                }
                else
                {
                    LogErrors("Creating user", result);
                    return(new ExternalUserResult(result, info));
                }
            }
        }