Search code examples
c#asp.netasp.net-identitygoogle-authentication

Image url in Asp.Net 4.5 Webforms when using google authentication


I have a website in ASP.Net 4.5 (not ASP.Net Core) based on webforms.

I am using using the Google button on Login.aspx page to login the user, that comes with the standard template in Visual Studio 2017 Community.

When I look at the code in Visual Studio 2017, I can see code that gets the authentication info against Google ( i.e. loginInfo variable in code below) in RegisterExternalLogin.aspx.cs, but when I inspect the object User.Identity.Claims after authentication in another page's code-behind (like in About.aspx.cs), then I find that there is no claim for image url of logged in user.

Question

Is it possible to get image url from Google using existing ASP.Net Identity/OWIN authentication in .Net framework 4.5 (not ASP.Net Core)? If yes, then how would one go about getting it?

Code executed after Google authentication in RegisterExternalLogin.aspx.cs

 if (!IsPostBack)
        {
            var manager = new UserManager();
            var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo();
            if (loginInfo == null)
            {
                Response.Redirect("~/Account/Login");
            }
            var user = manager.Find(loginInfo.Login);
            if (user != null)
            {
                IdentityHelper.SignIn(manager, user, isPersistent: false);
                IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
            }

Solution

  • After some research, I found how to get the profile image url using standard ASP.Net Identity/OWIN in a webforms ASP.Net app.

    It must be noted that the response from google after successful authentication already contains the profile image url, but since its not being extracted from the response and made available by asp. net identity/owin framework code, it appears as if the image url is not there . So, all we need to do is extract this pic url and put it into asp.net claims object. (no need to make a special call to google for profile image url)

    You need to make following 2 changes to the standard code that's emitted by the Visual Studio template.

    1. In Startup.Auth.cs add custom code that executes when Google authenticates completes its operation and returns its response. This custom code is within the OnAuthenticated function. We will access the profile image url, which can be found by going through children of context.User object, and add a claim for that to Google's context.Identity.

    In Startup.Auth.cs

        var options = new GoogleOAuth2AuthenticationOptions()
        {
           ClientId = "someValue1",
           ClientSecret = "someValue2",
           //ADD CODE AS BELOW in addition to above 2 lines
           Provider = new GoogleOAuth2AuthenticationProvider()
           {
            OnAuthenticated = (context) =>
             {
                //following line will add a new claim for profile image url
                context.Identity.AddClaim(new Claim("picUrl", ((Newtonsoft.Json.Linq.JValue)(context.User.SelectToken("image").SelectToken("url"))).Value.ToString()));
                return Task.FromResult(0);
             }
           }
    
        };
    
    1. When user is being signed in using the standard code's IdentityHelper.SignIn method, then we need to transfer the Google Identity Claim for image to ASP.Net Identity Claim. After this, we can access the image url in code-behind of any aspx page as shown in code-snippet at end of this answer.

    In IdentityModels.cs

    public static void SignIn(UserManager manager, ApplicationUser user, bool isPersistent)
    {
        IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
        authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        var identity = manager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
    
        //CUSTOM CODE Start
        //get image url claim from Google Identity
       if (authenticationManager.GetExternalLoginInfo().Login.LoginProvider == "Google")
         {
            var externalIdentity = authenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
            var picClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type.Equals("picUrl"));
            var picUrl = picClaim.Value;
            //add a claim for profile pic url to ASP.Net Identity
            identity.AddClaim(new System.Security.Claims.Claim("picUrl", picUrl));
         }
        //CUSTOM CODE end
    
        authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent , ExpiresUtc = DateTime.UtcNow.AddMinutes(5), RedirectUri="http://www,appsprocure.com"  }, identity);
    }
    

    Now, whenever you want to use the profile image url, simply use code like below.

    How to use image url claim in code-behind of pages

    var ctx = Request.GetOwinContext();
    ClaimsPrincipal user = ctx.Authentication.User;
    IEnumerable<Claim> claims = user.Claims;
    var pictureClaim = claims.FirstOrDefault(c => c.Type == "picUrl");
    if (pictureClaim != null)
    {
        Response.Write(string.Format("<img src='{0}' alt='profileImageMissing' />", pictureClaim.Value));
    }