【问题标题】:WebApi Facebook authentication with email addressWebApi Facebook 身份验证与电子邮件地址
【发布时间】:2023-03-22 14:35:01
【问题描述】:

我想使用他们的 Facebook 电子邮件地址让我的用户登录。我已经配置了我的 Facebook 身份验证:

var facebookAuthenticationOptions = new FacebookAuthenticationOptions
{
    AppId = facebookId,
    AppSecret = facebookSecret,
    Provider = new FacebookProvider()
};
app.UseFacebookAuthentication(facebookAuthenticationOptions);

我已覆盖 Facebook 提供程序以返回电子邮件地址:

public class FacebookProvider : FacebookAuthenticationProvider
{
    public override Task Authenticated(FacebookAuthenticatedContext context)
    {
        var accessTokenClaim = new Claim("ExternalAccessToken", context.AccessToken, "urn:facebook:access_token");
        context.Identity.AddClaim(accessTokenClaim);
        var extraClaims = GetAdditionalFacebookClaims(accessTokenClaim);
        context.Identity.AddClaim(new Claim(ClaimTypes.Email, extraClaims.First(k => k.Key == "email").Value.ToString()));
        context.Identity.AddClaim(new Claim("Provider", context.Identity.AuthenticationType));
        context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirstValue(ClaimTypes.Name)));

        var userDetail = context.User;
        var link = userDetail.Value<string>("link") ?? string.Empty;
        context.Identity.AddClaim(new Claim("link", link));
        context.Identity.AddClaim(new Claim("FacebookId", userDetail.Value<string>("id")));
        return Task.FromResult(0);
    }

    private static JsonObject GetAdditionalFacebookClaims(Claim accessToken)
    {
        var fb = new FacebookClient(accessToken.Value);
        return fb.Get("me", new { fields = new[] { "email" } }) as JsonObject;
    }

在 MVC 中一切正常 - 在 LoginOwinCallback 函数中,我能够检索从 Facebook 返回的用户电子邮件地址。我正在尝试使用令牌身份验证而不是外部 cookie 在 WebApi 中实现相同的目标。但是,虽然我可以看到我的提供商将电子邮件声明添加到响应中,但是当我在以下例程中调用 AuthenticateAsync 方法时,电子邮件声明不包括在内。

private async Task<ExternalLoginInfo> GetExternalLoginInfoAsync()
{
    var result = await Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer);

    if (result == null || result.Identity == null) return null;

    var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier);
    if (idClaim != null)
    {
        return new ExternalLoginInfo()
        {
            DefaultUserName = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""),
            ExternalIdentity = result.Identity,
            Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value)
        };
    }

    return null;
}

任何想法我做错了什么?

【问题讨论】:

    标签: asp.net-mvc facebook authentication asp.net-web-api oauth-2.0


    【解决方案1】:

    对于面临同样问题的其他人,可以使用电子邮件声明 - 只是有点隐藏。

    首先,要从 Facebook 正确检索用户的电子邮件地址,Startup.Auth.cs 的 ConfigureAuth 方法中的身份验证设置应该是:

    app.UseFacebookAuthentication(new FacebookAuthenticationOptions
    {
        AppId = facebookId,
        AppSecret = facebookSecret,
        Scope= {"email"},
        UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=email"
    });
    

    在MVC AccountController 类的LoginOwinCallback 方法中,邮箱地址在var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); 返回的ExternalLoginInfo 对象的Email 属性中。

    要在 WebAPI AccountController 类中检索电子邮件地址,您需要将 User.Identity 对象转换为 ClaimsIdentity 类型。

    [OverrideAuthentication]
    [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
    [AllowAnonymous]
    [Route("ExternalLogin", Name = "ExternalLogin")]
    public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
    {
        if (error != null)
        {
            return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
        }
    
        if (!User.Identity.IsAuthenticated)
        {
            return new ChallengeResult(provider, this);
        }
    
        // get all of the claims
        var claimsIdentity = User.Identity as ClaimsIdentity;  // this cast exposes all of the claims returned by Facebook
    
        // get the external login details
        var externalLogin = ExternalLoginData.FromIdentity(claimsIdentity);
    
        if (externalLogin == null)
        {
            return InternalServerError();
        }
    
        if (externalLogin.LoginProvider != provider)
        {
               AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            return new ChallengeResult(provider, this);
        }
    
        var user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
                externalLogin.ProviderKey));
    
        var hasRegistered = user != null;
    
        if (hasRegistered)
        {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    
            var oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
                OAuthDefaults.AuthenticationType);
            var cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
                CookieAuthenticationDefaults.AuthenticationType);
    
            var properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
            AuthenticationManager.SignIn(properties, oAuthIdentity, cookieIdentity);
        }
        else
        {
            var claims = claimsIdentity?.Claims ?? externalLogin.GetClaims();
            var identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
            AuthenticationManager.SignIn(identity);
        }
    
        return Ok();
    }
    

    这意味着您可以使用身份上的FindFirst 方法来查找 Facebook 返回的电子邮件声明。

    【讨论】:

      猜你喜欢
      • 2017-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多