Q:

Web API facebook, email claim returns null

Code is as follows
startup auth:
        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" }
        });

in the accountcontroler RegisterExternal class i call the following: 
var info = await AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer();
Which is this 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;
    }

This is because the RegisterExternal class on default will use authentication type cookie. Whenever i use it it will return null, so after surfing the web I've noticed it is necessary add this code which in turn will use the bearer for authentication, this will result in a reply where the username and the identity are no longer null, thus authorized. (see picture below)
Return object (username and login)
But, when i want to claim the email, i cannot do this. It will always return null no matter what i do. 

A:

I was running into the same issue and solved it by using the Facebook nuget package to get extra fields.
In my application I have implemented FacebookAuthenticationProvider and overridden the Authenticated(...) method with the following:
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;
    }
}

My Startup.cs has this within Configuration(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);

I've no idea why the email was not being populated in the first place, but this approach worked for me.

