Search code examples
c#asp.net-mvcgmailgoogle-plus

How to get google plus profile picture in c# MVC authentication


I'm developing a C# ASP.NET MVC 5 application that uses Google sign in as a default provider. The login functionality works ok and I can get the e-mail and name of the user. One thing that I need is to get the profile picture of the user.

How can I achieve that?

So far I using the default MVC auth "UseGoogleAuthentication".

Microsoft.Owin.Security.Google.GoogleAuthenticationOptions a = new Microsoft.Owin.Security.Google.GoogleAuthenticationOptions();

var googleOption = new GoogleAuthenticationOptions()
{
    Provider = new GoogleAuthenticationProvider()
    {
         OnAuthenticated = (context) =>
         {
              var rawUserObjectFromFacebookAsJson = context.Identity;
              context.Identity.AddClaim(new Claim("urn:google:name", context.Identity.FindFirstValue(ClaimTypes.Name)));
              context.Identity.AddClaim(new Claim("urn:google:email", context.Identity.FindFirstValue(ClaimTypes.Email)));
              return Task.FromResult(0);
         }
    }
};

app.UseGoogleAuthentication(googleOption);

This is how I can get the email address. But what about the profile picture?

Do I need to use another form of authentication?


Solution

  • I know this is a late answer, but found your question while working on the same problem. Here is my solution.

    Instead of using GoogleAuthenticationOptions I used GoogleOAuth2AuthenticationOptions which means you'll need to set up a project at https://console.developers.google.com/project first to get a ClientId and ClientSecret.

    1. At that link (https://console.developers.google.com/project), create a project and then select it.

    2. Then on the left side menu, click on "APIs & auth".

    3. Under "APIs", ensure you have "Google+ API" set to "On".

    4. Then click on "Credentials" (in the left side menu).

    5. Then click on the button "Create new Client ID". Follow the instructions and you will then be provided with a ClientId and ClientSecret, take note of both.

    Now you have those, the GoogleOAuth2AuthenticationOptions code looks like this:

    var googleOptions = new GoogleOAuth2AuthenticationOptions()
    {
        ClientId = [INSERT CLIENT ID HERE],
        ClientSecret = [INSERT CLIENT SECRET HERE],
        Provider = new GoogleOAuth2AuthenticationProvider()
        {
            OnAuthenticated = (context) =>
            {
                context.Identity.AddClaim(new Claim("urn:google:name", context.Identity.FindFirstValue(ClaimTypes.Name)));
                context.Identity.AddClaim(new Claim("urn:google:email", context.Identity.FindFirstValue(ClaimTypes.Email)));
                //This following line is need to retrieve the profile image
                context.Identity.AddClaim(new System.Security.Claims.Claim("urn:google:accesstoken", context.AccessToken, ClaimValueTypes.String, "Google"));
    
                return Task.FromResult(0);
            }
        }
    };
    
    app.UseGoogleAuthentication(googleOptions);
    

    Notice that this also adds the access token as a claim so we can use it to retrieve the profile image. The next bit may vary depending on how you have your project set up, but for me, it was in the AccountController.

    In my ExternalLoginCallback method I check for which login provider is being used and handle the data for Google login. In this section I retrieve the profile image url and store it in a variable with the following code:

    //get access token to use in profile image request
    var accessToken = loginInfo.ExternalIdentity.Claims.Where(c => c.Type.Equals("urn:google:accesstoken")).Select(c => c.Value).FirstOrDefault();
    Uri apiRequestUri = new Uri("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + accessToken);
    //request profile image
    using (var webClient = new System.Net.WebClient())
    {
        var json = webClient.DownloadString(apiRequestUri);
        dynamic result = JsonConvert.DeserializeObject(json);
        userPicture = result.picture;
    }
    

    This uses the access token to request the user info from google. It then retrieves the image url from the json data return. You can then save the url to the database in the most appropriate way for your project.

    Hope that helps someone.