[英]How to retrieve Google profile picture from logged in user with ASP.Net Core Identity?
Ok... I'm currently using ASP.Net Core 1.1.2 with ASP.NET Core Identity 1.1.2.好的...我目前正在使用 ASP.NET Core 1.1.2 和 ASP.NET Core Identity 1.1.2。
The important part in Startup.cs looks like this: Startup.cs 中的重要部分如下所示:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//...
app.UseGoogleAuthentication(new GoogleOptions
{
AuthenticationScheme = "Google",
SignInScheme = "Identity.External", // this is the name of the cookie middleware registered by UseIdentity()
ClientId = Configuration["ExternalLoginProviders:Google:ClientId"],
ClientSecret = Configuration["ExternalLoginProviders:Google:ClientSecret"]
});
}
GoogleOptions comes with Microsoft.AspNetCore.Authentication.Google nuget package. GoogleOptions 带有 Microsoft.AspNetCore.Authentication.Google nuget 包。
The callback function in AccountController.cs looks like this: AccountController.cs 中的回调函数如下所示:
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
//... SignInManager<User> _signInManager; declared before
ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();
SignInResult signInResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
string email = info.Principal.FindFirstValue(ClaimTypes.Email);
string firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
string lastName = info.Principal.FindFirstValue(ClaimTypes.Surname);
//
}
So, everything works fine until this point.所以,到目前为止一切正常。 And here I'm stuck.
我被困在这里。 I read a lot of articles about accesstokens and claims called pictureUrl and so on.
我阅读了很多关于访问令牌和声明的文章,称为 pictureUrl 等。 But the Principal doesn't contain any of those.
但是 Principal 不包含任何这些。
So the question is: How to retrieve the profile image once in the ExternalLoginCallback function?所以问题是:如何在 ExternalLoginCallback 函数中检索一次个人资料图像?
I struggled with the same problem but on ASP.NET Core 2.0.我在 ASP.NET Core 2.0 上遇到了同样的问题。 There is a better aproach to retrieve the picture from the
OnCreatingTicket
event in your startup.cs
.有一种更好的方法可以从
startup.cs
的OnCreatingTicket
事件中检索图片。 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.然后在您的 AccountController 中,您可以从外部登录信息方法中选择图像。
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.对于.net core 3.0+,微软使用System.Text.Json来处理google返回的对象,所以我们需要使用这个新API的GetProperty方法来获取图片。
https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/ 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;
};
});
Google is starting to shut down Google+ Signin for applications as early as January 28th 2019.谷歌最早将于 2019 年 1 月 28 日开始关闭应用程序的 Google+ 登录。
https://github.com/aspnet/AspNetCore/issues/6486 https://github.com/aspnet/AspNetCore/issues/6486
So we have to do following changes to accepted answer by @mtrax :因此,我们必须对@mtrax 接受的答案进行以下更改:
.AddGoogle(o =>
{
o.ClientId = Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
o.UserInformationEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
o.ClaimActions.Clear();
o.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
o.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
o.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
o.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
o.ClaimActions.MapJsonKey("urn:google:profile", "link");
o.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
o.ClaimActions.MapJsonKey("image", "picture");
});
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.
最后,我找到了一个使用 nameidentifier 的解决方案,它随声明一起提供。
string googleApiKey = "{your google api key}";
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.您只需要一个 Google API 密钥。
To create an API key:要创建 API 密钥:
a. a. In the list of Google APIs, search for the Google+ API service.
在 Google API 列表中,搜索 Google+ API 服务。
b.湾Select Google+ API from the results list.
从结果列表中选择 Google+ API。
c. C. Press the Enable API button.
按启用 API 按钮。
When the process completes, Google+ API appears in the list of enabled APIs.该过程完成后,Google+ API 会出现在启用的 API 列表中。 To access, select APIs & Services on the left sidebar menu, then select the Enabled APIs tab.
要访问,请在左侧边栏菜单中选择 API 和服务,然后选择启用的 API 选项卡。
https://developers.google.com/+/web/api/rest/oauth https://developers.google.com/+/web/api/rest/oauth
You can provide additional scopes you want to request in die GoogleOptions
setup.您可以在
GoogleOptions
设置中提供您想要请求的其他范围。 The scope you are looking for is the profile
scope, grating access to the firstname, lastname and profile picture via additional claims: https://developers.google.com/identity/protocols/OpenIDConnect#discovery您正在寻找的范围是
profile
范围,通过附加声明可以访问名字、姓氏和个人资料图片: https : //developers.google.com/identity/protocols/OpenIDConnect#discovery
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//...
app.UseGoogleAuthentication(new GoogleOptions
{
AuthenticationScheme = "Google",
SignInScheme = "Identity.External", // this is the name of the cookie middleware registered by UseIdentity()
ClientId = Configuration["ExternalLoginProviders:Google:ClientId"],
ClientSecret = Configuration["ExternalLoginProviders:Google:ClientSecret"]});
Scopes = { "profile" };
}
Then you can retrieve the picture claim in the controller after the authentication succeeds:然后你可以在认证成功后在控制器中检索图片声明:
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
//... SignInManager<User> _signInManager; declared before
ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();
SignInResult signInResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
string email = info.Principal.FindFirstValue(ClaimTypes.Email);
string firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
string lastName = info.Principal.FindFirstValue(ClaimTypes.Surname);
// profile claims
string picture = info.Principal.FindFirstValue("picture");
string firstName = info.Principal.FindFirstValue("given_name");
string lastName = info.Principal.FindFirstValue("family_name");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.