googleapis / google-api-dotnet-client

Google APIs Client Library for .NET
https://developers.google.com/api-client-library/dotnet
Apache License 2.0
1.35k stars 525 forks source link

.net api for getting username #1332

Closed stefanolson closed 5 years ago

stefanolson commented 5 years ago

I received an email today telling me that the API that I'm using to get the username of the user that I have logged in as is being deprecated e.g: "It includes Google+ OAuth scope requests, which are also affected by the Google+ shutdown".

I'm only using one call: var oauthSerivce = new Oauth2Service(new BaseClientService.Initializer {HttpClientInitializer = credential}); var userInfo = await oauthSerivce.Userinfo.Get().ExecuteAsync(); var username = userInfo.Id,

But from reading around I can't find what the correct replacement would be within the existing .net API.

What changes do I need to make in order to ensure this works? None of the documentation seems to mention the .net API around this area.

Thanks.

jskeet commented 5 years ago

(Assigning to Chris to look into this as I'm at a conference this week.)

jaglick commented 5 years ago

I'm running into a similar issue. I think I've actually traced it back to the scope configuration at the https://console.developers.google.com/apis/credentials rather than with the client package, but I'm not positive. In the screenshot below, you can see that the openid scope clearly uses the plus.me API. However it cannot be removed if you are using OAuth client ids.

image

chrisdunelm commented 5 years ago

I'm not familiar with the email that's been sent to you regarding Google+ shutdown.

However, here are some thoughts on this: The userInfo.Id property that you are retrieving appears to be a user-ID from Google. In my case it's a ~20-digit decimal number. This same ID can be retrieved from the JWT-token acquired during oauth:

using (var f = File.OpenRead("path/to/your/oauth.json"))
{
    var userCredential = GoogleWebAuthorizationBroker.AuthorizeAsync(f, new[] { "openid" }, "myuser", CancellationToken.None).Result;
    var jwtPayload = GoogleJsonWebSignature.ValidateAsync(userCredential Token.IdToken).Result;
    var username = jwtPayload.Subject;
}

Google is a conforming OpenID Connect provider; which requires the openid scope to be present. See the spec for details. So I don't see how this can be directly to do with the presence of an openid scope in the auth request.

stefanolson commented 5 years ago

Thanks Chris. What I'm actually looking for is the user's email address, so someone using multiple accounts in my software is able to know which one they want to deal with. The previously documented way appears to be being removed. And it's not really clear what to use now, especially with .net.

jaglick commented 5 years ago

@stefanolson, are you using OAuth 2.0? If you're not, I'll open a separate item for my issue. I initially thought it was the same issue because of your reference to the email notifying you that you were still using the Google+ API.

stefanolson commented 5 years ago

@jaglick Yes, I'm calling the oauth API in the sample code above simply because that was the way that you were supposed to get the user's email address. I'm not entirely sure if it's exactly the same issue but certainly any call to plus.me, which you are talking about needs to be replaced by something else. Exactly how to do that I'm not sure.

jaglick commented 5 years ago

And if you log into the developer's console and look at the scopes your credentials are using, does the tooltip show that the openid scope is still using plus.me?

stefanolson commented 5 years ago

@jaglick Not sure exactly what I'm looking for - is this what you mean: image from https://console.developers.google.com/apis/credentials/consent?project=

Open ID is certainly plusme email is https://www.googleapis.com/auth/userinfo.email

But I'm not sure how to access that email via User info.email from the .net API and whether that is part of Google plus or not? Seems to be a great deal of confusion about what is being shut and what is not

stefanolson commented 5 years ago

So I just followed through Fidler to check what is being called, and the API I'm using above calls this: https://www.googleapis.com/oauth2/v2/userinfo

Which is different than either of the options in the console above. And it is returning links to plus.google.com. And obviously I received the email from Google saying that I'm using plus.me, even though that's the only possible API call that's using the oauth API.

So I'm just not clear whether what is being shipped currently is going to break when Google+ disappears.

jaglick commented 5 years ago

Yes, that's the screen I'm referring to. I guess we'll just have to wait for someone from Google to chime in. Clearly something is calling the plus.me API even though we aren't calling it directly. For me, the intermittent failures referred to here are apparently causing some of my users to get access denied errors, while others don't.

chrisdunelm commented 5 years ago

I don't know why the "openid" scope appears to be linked to Google+. As far as I know, OpenID is independent of Google+; I've asked internally for clarification.

jaglick commented 5 years ago

@chrisdunelm Thanks for looking into it!

jaglick commented 5 years ago

@chrisdunelm, any udate?

jaglick commented 5 years ago

@chrisdunelm, did you ever learn anything? About half my users can't log in to my site. (It's a corporate site restricted to users in our G Apps domain only.) The API is returning an access_denied, even if the user was previously able to log in. The issue began on January 29.

chrisdunelm commented 5 years ago

@jaglick I've not received any response to my internal help request. I'll follow-up further internally.

chrisdunelm commented 5 years ago

I've just had confirmation that the openid scope definitely has not, and will not be affected by the Google+ shutdown. The plus.me scope is an alias for the openid scope. the plus.me scope will eventually be deprecated and stop working, but the openid scope will not be affected by this.

So the observed problems are not related the use of the openid scope.

chrisdunelm commented 5 years ago

@jaglick Please can you:

And I'll investigate further.

jaglick commented 5 years ago

I'm attaching my MVC projects Startup.Auth.cs file, which contains the API scopes I'm requesting. I'm not making an API call outside the MS OWIN middleware, so I don't know exactly what OWIN is doing. I do have the latest release of both the Google and Microsoft NuGet packages installed.

For the users who are unable to log in, the ExternalLoginCallback is receiving a parameter of error=access_denied. Unfortunately I can't get any more detailed error. Tracing the calls made in Chrome, I am not seeing any references to the plus.me APIs or scopes.

Other users are able to sign in without issue, myself included. (Which makes troubleshooting a little difficult, because I can't reproduce the error with my own login.)

Startup.Auth.cs.zip

jaglick commented 5 years ago

In case it's of any help... I have our Application Type set to Internal on the Developer's console. If I attempt to log in with my personal Google account instead of my corporate account, the error message includes the following output:

access_type=offline
approval_prompt=auto
include_granted_scopes=true
openid_connect_request=true
display=page
scope=https://www.googleapis.com/auth/plus.me 
https://www.googleapis.com/auth/userinfo.email 
https://www.googleapis.com/auth/gmail.compose

So while I'm not directly referring to the plus.me scope, it is still definitely being called.

chrisdunelm commented 5 years ago

@jaglick I suspect this may be due to https://github.com/aspnet/AspNetKatana/issues/251. The OWIN middleware used the Google+ API until very recently. It looks like this has been fixed in https://github.com/aspnet/AspNetKatana/pull/253 And released in https://www.nuget.org/packages/Microsoft.Owin/4.0.1

Are you seeing this problem with Owin v4.0.1?

jaglick commented 5 years ago

Yes, I'm using Owin v4.0.1 and still having the issue. Should I be posting on the Owin thread instead?

image

jaglick commented 5 years ago

Ok, so I did some additional testing and found that the issue occurs when requesting scopes. In my Startup.Auth.cs file if I comment out all three of the following lines my users can log in:

googleCreds.Scope.Add("openid");
googleCreds.Scope.Add("email");
googleCreds.Scope.Add(GmailService.Scope.GmailCompose);

However, they no longer have permission to send emails from within the application. This:

image

is changed to this:

image

So this may still be an issue with the Microsoft.Owin.Security.Google.GoogleOAuth2AuthenticationProvider implementation rather than with the Google API itself.

Tratcher commented 5 years ago

Nothing has changed in Microsoft.Owin.Security.Google 4.0.1 with the scope management. Note if you do not provide any scopes then the handler adds "openid profile email" for you.

jaglick commented 5 years ago

@Tratcher I understand that nothing has changed. I'm wondering though if something needs to. :) If I request any additional scopes, login fails. ExternalLoginCallback is receiving a parameter of error=access_denied.

I need for my users to be able to send emails, which is what I used to do with the googleCreds.Scope.Add(GmailService.Scope.GmailCompose) line referenced above. Now they aren't authorized because the scope is not being requested.

Tratcher commented 5 years ago

Try adding the profile scope that's used in the default scenario.

jaglick commented 5 years ago

I'll give that a try...

jaglick commented 5 years ago

That fixed it! Thank you SO much for that! Interesting that it's worked without that for several years. But really glad to have it fixed now. :)

chrisdunelm commented 5 years ago

Closing as it looks like this has been resolved. Please leave a further comment if not.