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:
- Go to the Google API Console.
- From the project drop-down, select a project , or create a new one.
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.
In the sidebar under "APIs & Services", select Credentials.
- In the Credentials tab, select the New credentials drop-down list, and choose API key.
- 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.
- Enter a key Name, fill in any other fields as instructed, then select Create.
https://developers.google.com/+/web/api/rest/oauth