ASP.Net MVC 5 Google Authentication with Scope

12,667

Solution 1

If anyone's still having trouble with this with the latest Microsoft OWIN middleware (3.0.0+)...


I noticed from Fiddler that by default, the following scope is sent to accounts.google.com:

scope=openid%20profile%20email

If you add your own scope(s) via GoogleOAuth2AuthenticationOptions.Scope.Add(...), then the scope becomes:

scope=YOUR_SCOPES_ONLY

Therefore, you need to add the default scopes too (or at least, this fixed the issue for me):

var googlePlusOptions = new GoogleOAuth2AuthenticationOptions {
    ...
};

// default scopes
googlePlusOptions.Scope.Add("openid");
googlePlusOptions.Scope.Add("profile");
googlePlusOptions.Scope.Add("email");

// additional scope(s)
googlePlusOptions.Scope.Add("https://www.googleapis.com/auth/youtube.readonly");

Solution 2

So, I figured this out, with a lot of help from http://www.beabigrockstar.com/blog/google-oauth-sign-asp-net-identity. It turns out that the built in Google authentication provider for MVC is openId only. That's why adding a scope broke it. Using Fiddler, I was able to see the GET request to accounts.google.com, which included "scope=openid" in the querystring.

By switching to the GooglePlusOAuth2 provider in the link above, or on Nuget https://www.nuget.org/packages/Owin.Security.GooglePlus and using the provider name of "GooglePlus", I was able to succesfully add the scopes and still get back the login info from GetExternalLoginInfoAsync.

Solution 3

The changes Google has made to their auth mechanisms have been reflected in version 3.0.0 of Microsoft Owin middleware. As you have identified correctly, one of the changes have been moving the OAuth endpoint to Google+ (https://www.googleapis.com/plus/v1/people/me).
So, the key is to:

  1. upgrade the OWIN middleware to version 3.0.0
  2. enable Google+ API for your app in Google Developers Console
Share:
12,667
Rob Gibbens
Author by

Rob Gibbens

Updated on July 23, 2022

Comments

  • Rob Gibbens
    Rob Gibbens almost 2 years

    I'm trying to get ASP.Net MVC 5 Google OAuth2 authentication working correctly.

    When I set pass in a GoogleOauth2AuthenticationOptions without any scope, then I'm able to log in successfully.

    var googlePlusOptions = new GoogleOAuth2AuthenticationOptions
    {
        ClientId = googleClientId,
        ClientSecret = googleClientSecret,
        SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
        Provider = new GoogleOAuth2AuthenticationProvider()
        {
            OnAuthenticated = async ctx =>
            {
                ctx.Identity.AddClaim(new Claim("urn:tokens:googleplus:accesstoken", ctx.AccessToken));
            }
        },
    };
    
    app.UseGoogleAuthentication(googlePlusOptions);
    

    Then this call will return an ExternalLoginInfo object with all the properties set

    ExternalLoginInfo loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    

    When I add any scope though, then I don't get any login info returned. It's just null.

    var googlePlusOptions = new GoogleOAuth2AuthenticationOptions
    {
        ClientId = googleClientId,
        ClientSecret = googleClientSecret,
        SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
        Provider = new GoogleOAuth2AuthenticationProvider()
        {
            OnAuthenticated = async ctx =>
            {
                ctx.Identity.AddClaim(new Claim("urn:tokens:googleplus:accesstoken", ctx.AccessToken));
            }
        },
    };
    
    googlePlusOptions.Scope.Add(YouTubeService.Scope.Youtube);
    
    app.UseGoogleAuthentication(googlePlusOptions);
    

    Then the call to get external info just returns null.

    ExternalLoginInfo loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    

    In the Google dev console, I have the following APIs turned on..

    • Analytics API
    • BigQuery API
    • Google Cloud SQL
    • Google Cloud Storage
    • Google Cloud Storage JSON API
    • Google+ API
    • Google+ Domains API
    • Identity Toolkit API
    • YouTube Analytics API
    • YouTube Data API v3

    Something about adding scope to the options is breaking GetExternalLoginInfoAsync.