skip to Main Content

I have a .net core 2.0 app and am implementing external login providers like google, twitter, and facebook. I have the requirement to get the user’s display name and profile picture, and can’t find any documentaion of how to achieve this in .net core 2.0.

I add the authentication like this post: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/

Here are my twitter login and callback functions…

    [HttpGet]
    [Route("/api/security/login/type/socialmedia/twitter")]
    public IActionResult GetTwitterLogin(string redirect_uri)
    {
        ClientCallback = redirect_uri;
        string redirectUrl = "/api/security/login/type/socialmedia/twittercallback";
        var properties = SignInManager.ConfigureExternalAuthenticationProperties("Twitter", redirectUrl);
        return Challenge(properties, "Twitter");
    }

    [HttpGet]
    [Route("/api/security/login/type/socialmedia/twittercallback")]
    public async Task<HttpResponseMessage> GetTwitterCallBackAsync()
    {
        var info = await SignInManager.GetExternalLoginInfoAsync();

        var result = await SignInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
        if (result.Succeeded)
        {

        }
        else
        {

        }


        Response.StatusCode = (int)HttpStatusCode.OK;
        return null;
    }

It looks like you can get some items from info.Principal.Claims, but nothing for the user’s display name or profile picture.

How do you get the display name or profile picture for the various login providers?

2

Answers


  1. Chosen as BEST ANSWER

    I finally figured this out...you need to add claims when you configure the authentication. These claims look at the resulting json response and pulls items from it. The pertinent lines are the ClaimActions items.

     services.AddAuthentication()
                   .AddTwitter(twitterOptions =>
                   {
                       twitterOptions.ConsumerKey = cfg.SystemConfig["TwitterConsumerKey"];
                       twitterOptions.ConsumerSecret = cfg.SystemConfig["TwitterConsumerSecret"];
                       twitterOptions.SaveTokens = true;
                       twitterOptions.RetrieveUserDetails = true;
                       twitterOptions.ClaimActions.MapJsonKey("display-name", "name");
                       twitterOptions.ClaimActions.MapJsonKey("profile-image-url", "profile_image_url_https");
                   })
                   .AddFacebook(facebookOptions =>
                   {
                       facebookOptions.AppId = cfg.SystemConfig["FacebookClientId"];
                       facebookOptions.AppSecret = cfg.SystemConfig["FacebookClientSecret"];
                       facebookOptions.SaveTokens = true;
                       facebookOptions.ClaimActions.MapJsonKey("display-name", "name");
    
                   })
                   .AddGoogle(googleOptions => 
                   {
                       googleOptions.ClientId = cfg.SystemConfig["GoogleClientId"];
                       googleOptions.ClientSecret = cfg.SystemConfig["GoogleClientSecret"];
                       googleOptions.SaveTokens = true;
                       googleOptions.ClaimActions.MapJsonSubKey("profile-image-url", "image", "url");
                       googleOptions.ClaimActions.MapJsonKey("display-name", "displayName" );
                   });
    

    After getting the login information in your callback using

    var info = await SignInManager.GetExternalLoginInfoAsync();
    

    If populated successfully you can query the claims and find the values

     var profileImageClaim = info.Principal.Claims.Where(x => x.Type == "profile-image-url").FirstOrDefault();
    

    Facebook images are different from google and twitter and can be found using...

    var claim = info.Principal.Claims.Where(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").FirstOrDefault();
    var url = "http://graph.facebook.com/" + claim.Value + "/picture";
    

  2. In ASP.NET Core 2.0, FacebookOptions uses extension methods on ClaimActions to map the profile data returned by UserInformationEndpoint.

    ClaimActions.MapJsonKey(ClaimTypes.DateOfBirth, "birthday");
    

    In the mapping above, “birthday” is a top-level property in the Facebook Graph API response that’s mapped to the value represented by the claim ClaimTypes.DateOfBirth.

    To grab the profile picture you would do the same thing, but since the picture in the Graph API response is a nested JSON object, you would have to use MapCustomJson()

    services.AddAuthentication()
       .AddFacebook(options =>
        {
           // ...other options omitted
           options.Fields.Add("picture");
    
           options.ClaimActions.MapCustomJson("urn:facebook:picture", 
                            claim => (string)claim.SelectToken("picture.data.url"));
        })
    

    Here, claim is a NewtonSoft JObject that uses JPath syntax to select the nested property value and cast it to a string.

    The profile picture URL will now appear in your Claims list.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search