コード例 #1
0
    private async Task <SignInResult> LinkUser(MemberIdentityUser autoLinkUser, ExternalLoginInfo loginInfo)
    {
        IList <UserLoginInfo>?existingLogins = await UserManager.GetLoginsAsync(autoLinkUser);

        UserLoginInfo?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, false, loginInfo.LoginProvider));
        }

        IdentityResult?linkResult = await UserManager.AddLoginAsync(autoLinkUser, loginInfo);

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

        // If this fails, we should really delete the user since it will be in an inconsistent state!
        IdentityResult?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));
        }
    }
コード例 #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,
        MemberExternalSignInAutoLinkOptions?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);
        }

        // Now we need to perform the auto-link, so first we need to lookup/create a user with the email address
        MemberIdentityUser?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));
            }

            LogFailedExternalLogin(loginInfo, autoLinkUser);
            return(ExternalLoginSignInResult.NotAllowed);
        }

        var name = loginInfo.Principal?.Identity?.Name;

        if (name.IsNullOrWhiteSpace())
        {
            throw new InvalidOperationException("The Name value cannot be null");
        }

        autoLinkUser = MemberIdentityUser.CreateNew(email, email, autoLinkOptions.DefaultMemberTypeAlias, autoLinkOptions.DefaultIsApproved, name);

        foreach (var userGroup in autoLinkOptions.DefaultMemberGroups)
        {
            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));
        }

        IdentityResult?userCreationResult = await UserManager.CreateAsync(autoLinkUser);

        if (!userCreationResult.Succeeded)
        {
            return(AutoLinkSignInResult.FailedCreatingUser(
                       userCreationResult.Errors.Select(x => x.Description).ToList()));
        }

        {
            var shouldLinkUser = autoLinkOptions.OnExternalLogin == null ||
                                 autoLinkOptions.OnExternalLogin(autoLinkUser, loginInfo);
            if (shouldLinkUser)
            {
                return(await LinkUser(autoLinkUser, loginInfo));
            }

            LogFailedExternalLogin(loginInfo, autoLinkUser);
            return(ExternalLoginSignInResult.NotAllowed);
        }
    }