Search code examples
asp.net-coreasp.net-identity.net-coreprofileidentityserver4

How do I get profile pictures from external providers using identityserver4?


I'm using identityserver4 with Net Core. I can authenticate using Google, Facebook, Twitter, LinkedIn, and Microsoft but now I'd like to get the user's profile picture the external provider. I'm using a client with GrantTypes.Implicit and have tried adding a new IdentityResource as follows:

new IdentityResource {
    Name = "picture",
    UserClaims = new List<string> {"picture" }
}

I then added "picture" as an allowed scope for my client. This is all a shot in the dark though as I'm still trying to wrap my head around identity resources and allowed scopes.

Since I'm very new to identityserver4, be kind and be detailed as possible. Thanks in advance!


Solution

  • There should already be "scope" in the Identity Resources called "profile" having a set of User Claims- one of which is "picture".

    Since you are using ASP.NET Identity, you'll need to insert a record for any given user into AspNetUserClaims table with a claim type of "picture" where the value is the url of the online image.

    Clients that have been given the scope of "profile" should receive this "picture" claim when they make a request to the UserInfo endpoint.

    If you want to make that picture as part of the id_token, then you'll need to add the "picture" claim to the "openid" scope/resource in addition to the "profile" scope/resource.

    (The terms scope and resource blend together a little in Identity Server data model.)

    --

    To get the picture claim from Google you can do this:

    info.Principal.Claims.Where(x => x.Type == "picture").Select(x => x.Value).FirstOrDefault()
    

    --

    When using Microsoft.AspNetCore.Authentication.Google, i.e. app.UseGoogleAuthentication(google.Options(externalCookieScheme), Google doesn't send the picture claim.

    If you switch to using the OIDC method, then Google will send you the picture claim.

            app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
            {
                AuthenticationScheme = "oidc-google",
    
                DisplayName = "Google",
                Authority = "https://accounts.google.com",
                ClientId = "",
                ClientSecret = "",
                Scope = { "profile", "email", "openid" },
                CallbackPath = "signin-google",
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role",
                    ValidateIssuer = false
                }
            });