如何使用ASP.Net Core Identity从登录用户检索Google个人资料图片?

时间:2017-08-24 07:32:10

标签: c# asp.net-core google-api asp.net-identity google-oauth

好的......我目前正在使用ASP.Net Core 1.1.2和ASP.NET Core Identity 1.1.2。

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附带Microsoft.AspNetCore.Authentication.Google nuget包。

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);
        //
    }

所以,到目前为止,一切正常。在这里,我被困住了。我读了很多关于accessstokens和声称的文章,名为pictureUrl等。但校长不包含任何这些。

所以问题是:如何在ExternalLoginCallback函数中检索一次配置文件图像?

5 个答案:

答案 0 :(得分:7)

我在ASP.NET Core 2.0上遇到了同样的问题。 从OnCreatingTicket startup.cs事件中检索图片有一个更好的方法。在您的情况下,您必须将特定声明&#34;图片&#34; 添加到身份中。

    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;
                };
            });
    }

然后在您的AccountController中,您可以从外部登录信息方法中选择图像。

var info = await _signInManager.GetExternalLoginInfoAsync();

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

答案 1 :(得分:7)

对于.net core 3.0 +,Microsoft使用System.Text.Json来处理从Google返回的对象,因此我们需要使用此新API的GetProperty方法来获取图片。

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;
                    };
                });

答案 2 :(得分:1)

我发现无法从索赔中获取图片网址。最后,我找到了一个使用nameidentifier的解决方案,该解决方案随附声明。

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);
}

您只需要一个Google API密钥。

创建API密钥:

  1. 转到Google API控制台。
  2. 从项目下拉列表中选择一个项目,或者创建一个新项目。
  3. 启用Google+ API服务:

    一个。在Google API列表中,搜索Google+ API服务。

    湾从结果列表中选择Google+ API。

    ℃。按“启用API”按钮。

    此过程完成后,Google+ API会显示在已启用的API列表中。至 访问,选择API&amp;左侧边栏菜单上的服务,然后选择 启用API选项卡。

  4. 在&#34; API&amp;服务&#34;,选择凭据。

  5. 在“凭据”选项卡中,选择“新建凭据”下拉列表,然后选择“API密钥”。
  6. 从“创建新密钥”弹出窗口中,为项目选择适当的密钥类型:服务器密钥,浏览器密钥,Android密钥或iOS密钥。
  7. 输入密钥名称,按照说明填写任何其他字段,然后选择创建。
  8. https://developers.google.com/+/web/api/rest/oauth

答案 3 :(得分:0)

您可以在GoogleOptions设置中提供要请求的其他范围。您正在寻找的范围是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" };
    }

然后,您可以在身份验证成功后检索控制器中的图片声明:

    [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");
    }

答案 4 :(得分:0)

Google最早将于2019年1月28日开始关闭应用程序的Google+登录。

https://github.com/aspnet/AspNetCore/issues/6486

因此,我们必须对@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");
            });