Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access email address in the OAuth ExternalLoginCallback from Facebook v2.4 API in ASP.NET MVC 5 [duplicate]

With v2.3 of the Facebook API, provided the following was set, the users email address would be returned on the callback to ExternalLoginCallback;

app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
    AppId = "XXX",
    AppSecret = "XXX",
    Scope = { "email" }
});

However, any app that can only target v2.4 (released 8 July) no longer returns the email address to the ExternalLoginCallback.

I think this may possibly be related to the v2.4 changes as listed here;

Declarative Fields

To try to improve performance on mobile networks, Nodes and Edges in v2.4 requires that you explicitly request the field(s) you need for your GET requests. For example, GET /v2.4/me/feed no longer includes likes and comments by default, but GET /v2.4/me/feed?fields=comments,likes will return the data. For more details see the docs on how to request specific fields.

How can I access this email address now?

like image 430
Stafford Williams Avatar asked Jul 30 '15 02:07

Stafford Williams


2 Answers

To resolve this I had to install the Facebook SDK for .NET from nuget and query the email address separately.

In the ExternalLoginCallback method, I added a conditional to populate the email address from the Facebook Graph API;

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

if (loginInfo == null)
{
    return RedirectToAction("Login");
}

// added the following lines
if (loginInfo.Login.LoginProvider == "Facebook")
{
    var identity = AuthenticationManager.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
    var access_token = identity.FindFirstValue("FacebookAccessToken");
    var fb = new FacebookClient(access_token);
    dynamic myInfo = fb.Get("/me?fields=email"); // specify the email field
    loginInfo.Email = myInfo.email;
}

And to get the FacebookAccessToken I extended ConfigureAuth;

app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
    AppId = "XXX",
    AppSecret = "XXX",
    Scope = { "email" },
    Provider = new FacebookAuthenticationProvider
    {
        OnAuthenticated = context =>
        {
            context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
            return Task.FromResult(true);
        }
    }
});
like image 154
Stafford Williams Avatar answered Oct 10 '22 07:10

Stafford Williams


In MVC 6 (Asp.net Core 1.0), by configuring FacebookAuthentication in startup.cs like this:

         app.UseFacebookAuthentication(options =>
            {
                options.AppId = Configuration["Authentication:Facebook:AppId"];
                options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
                options.Scope.Add("email");
                options.UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name";
            });

I could get the email. I.e:

   var info = await _signInManager.GetExternalLoginInfoAsync();
   var email = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Email);
like image 20
Ole Kristian Losvik Avatar answered Oct 10 '22 08:10

Ole Kristian Losvik