Web API facebook,电子邮件声明 returns null

Web API facebook, email claim returns null

代码如下

启动授权:

        app.UseFacebookAuthentication(new FacebookAuthenticationOptions
        {
            AppId = "xxx",
            AppSecret = "xxx",
            BackchannelHttpHandler = new FacebookBackChannelHandler(),
            UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name,location",
            Scope = { "email" }
        });

在帐户控制器 RegisterExternal class 中,我调用以下内容:

var info = await AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer();

这是哪个class:

private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
    {
        ExternalLoginInfo loginInfo = null;

        var result = await Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer);

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

            }
        }
        return loginInfo;
    }

这是因为默认情况下 RegisterExternal class 将使用身份验证类型 cookie。每当我使用它时,它都会 return null,所以在网上冲浪后我注意到有必要添加这段代码,这反过来将使用承载进行身份验证,这将导致用户名和身份的回复不再为空,因此被授权。 (见下图)

Return object (username and login)

但是,当我想领取电子邮件时,我不能这样做。无论我做什么,它总是 return null。

我 运行 遇到了同样的问题,并通过使用 Facebook nuget 包获取额外字段解决了这个问题。

在我的应用程序中,我实现了 FacebookAuthenticationProvider 并使用以下内容覆盖了 Authenticated(...) 方法:

public class FacebookAuthProvider : 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 System.Threading.Tasks.Task.FromResult(0);
    }

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

我的 Startup.csConfiguration(IAppBuilder app) 内有这个:

FacebookAuthOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions
{
      AppId = "YOUR APP ID",
      AppSecret = "YOUR APP SECRET",
      Microsoft.Owin.PathString("/Account/ExternalCallBack"), // whatever your external callback url is
      Provider = new FacebookAuthProvider()
};
FacebookAuthOptions.Scope.Add("email");
app.UseFacebookAuthentication(FacebookAuthOptions);

我不知道为什么电子邮件没有首先被填充,但这种方法对我有用。