Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

The important part in Startup.cs looks like this:

    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.

The callback function in AccountController.cs looks like this:

    [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. But the Principal doesn't contain any of those.

So the question is: How to retrieve the profile image once in the ExternalLoginCallback function?

like image 300
Norman Avatar asked Aug 24 '17 07:08

Norman


Video Answer


2 Answers

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");
like image 199
emcoding Avatar answered Oct 01 '22 14:10

emcoding


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;
                    };
                });
like image 20
mesut Avatar answered Oct 01 '22 15:10

mesut