How to retrieve Google profile picture from logged in user with ASP.Net Core Identity?

I struggled with the same problem but on ASP.NET Core 2.0. There is a better aproach to retrieve the picture from the OnCreatingTicket event in your startup.cs. In your case you have to add the specific claim "picture" to the identity.

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddAuthentication()
            .AddCookie()
            .AddGoogle(options =>
            {
                options.ClientId = Configuration["Google.LoginProvider.ClientId"];
                options.ClientSecret = Configuration["Google.LoginProvider.ClientKey"];
                options.Scope.Add("profile");
                options.Events.OnCreatingTicket = (context) =>
                {
                    context.Identity.AddClaim(new Claim("image", context.User.GetValue("image").SelectToken("url").ToString()));

                    return Task.CompletedTask;
                };
            });
    }

Then in your AccountController you can select the image from the external login info method.

var info = await _signInManager.GetExternalLoginInfoAsync();

var picture = info.Principal.FindFirstValue("image");

For .net core 3.0+, Microsoft uses System.Text.Json for handling returned object from google, so we need to use GetProperty method of this new API to get picture.

https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/

services.AddAuthentication()
                .AddGoogle(options =>
                {
                    IConfigurationSection googleAuthNSection = Configuration.GetSection("Authentication:Google");

                    options.ClientId = googleAuthNSection["ClientId"];
                    options.ClientSecret = googleAuthNSection["ClientSecret"];
                    options.Scope.Add("profile");
                    options.Events.OnCreatingTicket = (context) =>
                    {                      
                        var picture = context.User.GetProperty("picture").GetString();

                        context.Identity.AddClaim(new Claim("picture", picture));

                        return Task.CompletedTask;
                    };
                });

I found no way to get the picture url from the claims. Finally I found a solution using the nameidentifier, which comes with the claims.

string googleApiKey = _configurationRoot["ExternalLoginProviders:Google:ApiKey"];
ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();
string nameIdentifier = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
string jsonUrl = $"https://www.googleapis.com/plus/v1/people/{nameIdentifier}?fields=image&key={googleApiKey}";
using (HttpClient httpClient = new HttpClient())
{
    string s = await httpClient.GetStringAsync(jsonUrl);
    dynamic deserializeObject = JsonConvert.DeserializeObject(s);
    string thumbnailUrl = (string)deserializeObject.image.url;
    byte[] thumbnail = await httpClient.GetByteArrayAsync(thumbnailUrl);
}

All you need is a Google API key.

To create an API key:

  1. Go to the Google API Console.
  2. From the project drop-down, select a project , or create a new one.
  3. Enable the Google+ API service:

    a. In the list of Google APIs, search for the Google+ API service.

    b. Select Google+ API from the results list.

    c. Press the Enable API button.

    When the process completes, Google+ API appears in the list of enabled APIs. To access, select APIs & Services on the left sidebar menu, then select the Enabled APIs tab.

  4. In the sidebar under "APIs & Services", select Credentials.

  5. In the Credentials tab, select the New credentials drop-down list, and choose API key.
  6. From the Create a new key pop-up, choose the appropriate kind of key for your project: Server key, Browser key, Android key, or iOS key.
  7. Enter a key Name, fill in any other fields as instructed, then select Create.

https://developers.google.com/+/web/api/rest/oauth