Ejemplo n.º 1
0
        private async Task <SignInResult> LinkUser(BackOfficeIdentityUser autoLinkUser, ExternalLoginInfo loginInfo)
        {
            var existingLogins = await _userManager.GetLoginsAsync(autoLinkUser);

            var exists = existingLogins.FirstOrDefault(x => x.LoginProvider == loginInfo.LoginProvider && x.ProviderKey == loginInfo.ProviderKey);

            // if it already exists (perhaps it was added in the AutoLink callbak) then we just continue
            if (exists != null)
            {
                //sign in
                return(await SignInOrTwoFactorAsync(autoLinkUser, isPersistent : false, loginInfo.LoginProvider));
            }

            var linkResult = await _userManager.AddLoginAsync(autoLinkUser, loginInfo);

            if (linkResult.Succeeded)
            {
                //we're good! sign in
                return(await SignInOrTwoFactorAsync(autoLinkUser, isPersistent : false, loginInfo.LoginProvider));
            }

            //If this fails, we should really delete the user since it will be in an inconsistent state!
            var deleteResult = await _userManager.DeleteAsync(autoLinkUser);

            if (deleteResult.Succeeded)
            {
                var errors = linkResult.Errors.Select(x => x.Description).ToList();
                return(AutoLinkSignInResult.FailedLinkingUser(errors));
            }
            else
            {
                //DOH! ... this isn't good, combine all errors to be shown
                var errors = linkResult.Errors.Concat(deleteResult.Errors).Select(x => x.Description).ToList();
                return(AutoLinkSignInResult.FailedLinkingUser(errors));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Used for auto linking/creating user accounts for external logins
        /// </summary>
        /// <param name="loginInfo"></param>
        /// <param name="autoLinkOptions"></param>
        /// <returns></returns>
        private async Task <SignInResult> AutoLinkAndSignInExternalAccount(ExternalLoginInfo loginInfo, ExternalSignInAutoLinkOptions?autoLinkOptions)
        {
            // If there are no autolink options then the attempt is failed (user does not exist)
            if (autoLinkOptions == null || !autoLinkOptions.AutoLinkExternalAccount)
            {
                return(SignInResult.Failed);
            }

            var email = loginInfo.Principal.FindFirstValue(ClaimTypes.Email);

            //we are allowing auto-linking/creating of local accounts
            if (email.IsNullOrWhiteSpace())
            {
                return(AutoLinkSignInResult.FailedNoEmail);
            }
            else
            {
                //Now we need to perform the auto-link, so first we need to lookup/create a user with the email address
                var autoLinkUser = await UserManager.FindByEmailAsync(email);

                if (autoLinkUser != null)
                {
                    try
                    {
                        //call the callback if one is assigned
                        autoLinkOptions.OnAutoLinking?.Invoke(autoLinkUser, loginInfo);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(ex, "Could not link login provider {LoginProvider}.", loginInfo.LoginProvider);
                        return(AutoLinkSignInResult.FailedException(ex.Message));
                    }

                    var shouldLinkUser = autoLinkOptions.OnExternalLogin == null || autoLinkOptions.OnExternalLogin(autoLinkUser, loginInfo);
                    if (shouldLinkUser)
                    {
                        return(await LinkUser(autoLinkUser, loginInfo));
                    }
                    else
                    {
                        LogFailedExternalLogin(loginInfo, autoLinkUser);
                        return(ExternalLoginSignInResult.NotAllowed);
                    }
                }
                else
                {
                    var name = loginInfo.Principal?.Identity?.Name;
                    if (name.IsNullOrWhiteSpace())
                    {
                        throw new InvalidOperationException("The Name value cannot be null");
                    }

                    autoLinkUser = BackOfficeIdentityUser.CreateNew(_globalSettings, email, email, autoLinkOptions.GetUserAutoLinkCulture(_globalSettings), name);

                    foreach (var userGroup in autoLinkOptions.DefaultUserGroups)
                    {
                        autoLinkUser.AddRole(userGroup);
                    }

                    //call the callback if one is assigned
                    try
                    {
                        autoLinkOptions.OnAutoLinking?.Invoke(autoLinkUser, loginInfo);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(ex, "Could not link login provider {LoginProvider}.", loginInfo.LoginProvider);
                        return(AutoLinkSignInResult.FailedException(ex.Message));
                    }

                    var userCreationResult = await _userManager.CreateAsync(autoLinkUser);

                    if (!userCreationResult.Succeeded)
                    {
                        return(AutoLinkSignInResult.FailedCreatingUser(userCreationResult.Errors.Select(x => x.Description).ToList()));
                    }
                    else
                    {
                        var shouldLinkUser = autoLinkOptions.OnExternalLogin == null || autoLinkOptions.OnExternalLogin(autoLinkUser, loginInfo);
                        if (shouldLinkUser)
                        {
                            return(await LinkUser(autoLinkUser, loginInfo));
                        }
                        else
                        {
                            LogFailedExternalLogin(loginInfo, autoLinkUser);
                            return(ExternalLoginSignInResult.NotAllowed);
                        }
                    }
                }
            }
        }