Rob Gibbens
Rob Gibbens

Reputation: 1142

ASP.Net MVC 5 Google Authentication with Scope

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..

Something about adding scope to the options is breaking GetExternalLoginInfoAsync.

Upvotes: 9

Views: 13083

Answers (3)

Dunc
Dunc

Reputation: 18922

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

Upvotes: 12

Rob Gibbens
Rob Gibbens

Reputation: 1142

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.

Upvotes: 9

jansokoly
jansokoly

Reputation: 2104

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

Upvotes: 2

Related Questions