1

UPDATE: PLEASE SEE THIS POST: https://stackoverflow.com/a/20379623/687549

Been reading I think almost all questions on SO about external providers and how to get extra info/data/metadata/claims/orwhateveryouwannacallit in particular the email address which many use as the username on modern websites.

So the problem that I was facing was that I wanted to retrieve the email from the Facebook provider with as little code as possible. I thought to myself; the new ASP.NET Identity framework must have this buil-in and can do this with probably just a couple of lines of code. I searched and all I could find was these imensely large chunks of code and I thought to myself: there has got to be another more simpler way. And here it is, as an answer in this questionthread.

I managed to get this working with both Facebook and Google but what I'm concerned about is wheather or not I'm doing this right without any consequenses somewhere else in the code.

For instance: Do you really only need to specify the Scopes.Add("email") for it all to work or why haven't I been able to find more info about this on the interweb?

Community
  • 1
  • 1
PussInBoots
  • 11,028
  • 9
  • 52
  • 84
  • Without posting the code in question it's really hard for anyone to help you. – stink Dec 05 '13 at 14:26
  • @stink please se answer below.. was writing as you wrote your comment.. thanks. – PussInBoots Dec 05 '13 at 14:32
  • just do this tutorial http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on – stink Dec 05 '13 at 19:00
  • Already have. One of the first aritcles I read about asp.net identity. says nothing about getting email from externmal provider. – PussInBoots Dec 05 '13 at 19:55
  • You definitely have to have this `AppId = "myAppId", AppSecret = "myAppSecret"` for Facebook Authentication. – stink Dec 06 '13 at 01:44
  • Did you create an appId in Facebook Developer? – stink Dec 06 '13 at 01:47
  • @stink did you read my question and answer? yes, both google and facebook are working as per the tutorial you linked. the question is about the email. – PussInBoots Dec 06 '13 at 09:56

2 Answers2

2

UPDATE: PLEASE SEE THIS POST: https://stackoverflow.com/a/20379623/687549

Startup.Auth.cs:

var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
{
    AppId = "myAppId",
    AppSecret = "myAppSecret"
};
facebookAuthenticationOptions.Scope.Add("email");
app.UseFacebookAuthentication(facebookAuthenticationOptions);

AccountController (default mvc 5 template app stuff)

//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction("Login");
    }

    // These next three lines is how I get the email from the stuff that gets returned from the Facebook external provider
    var externalIdentity = HttpContext.GetOwinContext().Authentication.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
    var emailClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email);
    var email = emailClaim.Value;

    // Sign in the user with this external login provider if the user already has a login
    var user = await UserManager.FindAsync(loginInfo.Login);
    if (user != null)
    {
        await SignInAsync(user, isPersistent: false);
        return RedirectToLocal(returnUrl);
    }
    else
    {
        // If the user does not have an account, then prompt the user to create an account
        ViewBag.ReturnUrl = returnUrl;
        ViewBag.LoginProvider = loginInfo.Login.LoginProvider;

        // Populate the viewmodel with the email
        return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = email });
    }
}
Community
  • 1
  • 1
PussInBoots
  • 11,028
  • 9
  • 52
  • 84
  • The automatic code highlighting wasn't kicking in. Added it manually: http://stackoverflow.com/editing-help#syntax-highlighting – Nelson Reis Dec 19 '13 at 12:46
  • Your solution is *almost* complete (MVC 5). You missing one line in facebookAuthenticationOptions: UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name" – Illidan Apr 22 '17 at 05:50
0

I have the same problem. You need to edit and add this code to ExternalLoginCallback in the AccountController

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;
}

Note the code dynamic myInfo = fb.Get("/me?fields=email"); this will work for facebook app with version 2.4, but for old version you can write this

 dynamic myInfo = fb.Get("email");
Ahmed Shamel
  • 1,982
  • 3
  • 24
  • 58