ASN.NET Core 2.0 Facebook authentication ExternalLoginSignInAsync Fails (IsNotAllowed)

岁酱吖の 提交于 2019-12-07 13:30:51

问题


I am creating a new application in ASP.NET Core 2.0 with Ddentity. I have enabled the Facebook Authentication according to the docs.

The flow that is running right now is the following:

  1. When a new user authenticates from facebook the applicatiion asks for an email in order to be used for the application
  2. When the user provides the email a user is created in my dbo.AspNetUsers table with the email provided by the user and a new line is created in my dbo.AspNetUserLogins with the reference to the provider, the providerKey and the userId.
  3. At that point I can see that in my database all rows have correct data.

Now when the user logs out and tries to login again with facebook at some point the application checks if the user can login with the providers credentials through the:

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

At that point my result comes as NotAllowed (attribute IsNotAllowed = true) and it asks the user to enter a new email (Like the original flow for a new user). Of course then the email is already registered and the user can't create a new account as he shouldn't have to.

My controller for the ExternalLoginCallback is the default implementation of the project.

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
    {
        if (remoteError != null)
        {
            ErrorMessage = $"Error from external provider: {remoteError}";
            return RedirectToAction(nameof(Login));
        }
        var info = await _signInManager.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return RedirectToAction(nameof(Login));
        }

        // Sign in the user with this external login provider if the user already has a login.
        var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
            return RedirectToLocal(returnUrl);
        }
        if (result.IsLockedOut)
        {
            return RedirectToAction(nameof(Lockout));
        }
        else
        {
            // If the user does not have an account, then ask the user to create an account.
            ViewData["ReturnUrl"] = returnUrl;
            ViewData["LoginProvider"] = info.LoginProvider;
            var email = info.Principal.FindFirstValue(ClaimTypes.Email);
            return View("ExternalLogin", new ExternalLoginViewModel { Email = email });
        }
    }

Can anyone help me find what am I missing or what should I see in order to get the answer to this? Thanks you in advance.


回答1:


IsNotAllowed is set to true when you have set either RequireConfirmedEmail or RequireConfirmedPhoneNumber to true on SignInOptions (usually configured as part of AddIdentity) but the email address or phone number has not been confirmed.

If you don't want to require a confirmed email or phone number for external logins, you can set the relevant properties when creating your IdentityUser derived class after its first creation. e.g.:

var identityUser = new IdentityUser
{
    // ...
    EmailConfirmed = true,
    PhoneNumberConfirmed = true
};

Otherwise, if you do want the verification process to occur, you can follow the guide in the ASP.NET Core docs for the email address side of things.

You can see how all this works in the source code. You end up in PreSignInCheck:

if (!await CanSignInAsync(user))
{
    return SignInResult.NotAllowed;
}

The CanSignInAsync implementation looks like this (with logging removed):

public virtual async Task<bool> CanSignInAsync(TUser user)
{
    if (Options.SignIn.RequireConfirmedEmail &&
        !(await UserManager.IsEmailConfirmedAsync(user)))
    {
        return false;
    }

    if (Options.SignIn.RequireConfirmedPhoneNumber &&
        !(await UserManager.IsPhoneNumberConfirmedAsync(user)))
    {
        return false;
    }

    return true;
}


来源:https://stackoverflow.com/questions/47268027/asn-net-core-2-0-facebook-authentication-externalloginsigninasync-fails-isnotal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!