"Client is unauthorized to retrieve access tokens using this method" w/ Service Account
See original GitHub issueENVIRONMENT DETAILS
OS: Windows 10
.NET version: .net core 3.1
Package name and version: using Google.Apis.Auth.OAuth2
; (1.45.0)
END GOAL: Get OAuth2 token for Gmail User via service account created in free gmail account.
PROBLEM / CAUSE: I have an existing gmail account that is used by a .NET Core Application
to send and receive emails - bob@gmail.com
. The application now logs in to gmail with bob@gmail.com
and the password to send emails. This requires “less secure access” to be enabled, which doesn’t work when the project runs on Azure.
Consequently, the solution is to start using OAuth 2.0 for access.
I paid for a G-Suite account bob@mycompany.com
.
Questions which may make this easy to answer & close:
-
Will the service account authentication work without domain verification on the G-Suite account? If not, that’s my problem and this can be closed, but I would like a definitive answer if possible.
-
Will I be able to authenticate a service account from
bob@gmail.com
(free) withbob@mycompany.com
(paid G-Suite account)? The documentation doesn’t seem to mention it anywhere, but posts on stackoverflow said this will work. (i.e., is doing what’s shown in the screenshot below enough?)
If the above should theoretically work, here is my code which throws an exception when I try to fetch a JWT to use:
public async Task<IActionResult> GetToken()
{
using (var stream = new FileStream("my-magical-key-file.json", FileMode.Open, FileAccess.Read))
{
ServiceAccountCredential srvsAcctCred =
GoogleCredential.FromStream(stream)
.CreateScoped(new[] {
"https://mail.google.com/"
})
.CreateWithUser(SMTPConfigs.GMAIL_WITH_FORWARDED_LEADS.UserName)
.UnderlyingCredential as ServiceAccountCredential;
bool result = await srvsAcctCred.RequestAccessTokenAsync(CancellationToken.None);
}
The exception is thrown on RequestAccessTokenAsync
and is:
Google.Apis.Auth.OAuth2.Responses.TokenResponseException: 'Error:"unauthorized_client", Description:"Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.", Uri:""'
Commenting out this line .CreateWithUser(SMTPConfigs.GMAIL_WITH_FORWARDED_LEADS.UserName)
resolves the error, but obviously doesn’t create a token for the user.
Here is more information on my workflow / what I have done at a glance:
Issue Analytics
- State:
- Created 3 years ago
- Comments:14 (6 by maintainers)
Top GitHub Comments
Yes, I can confirm this won’t work, you can impersonate G-Suite accounts but not Gmail accounts, sorry for not catching this earlier. Take into account that:
Once a service account has been granted an API scope, it can make API requests using OAuth 2.0 by impersonating any user (including a super admin) in the G Suite account that:
I’ll wait for you tou acknowledge before closing but I believe this to have been answered, and unrelated to the Auth library.
Means that the domain wide delegation on the gSuite domain email has not been set up properly.
(Note i am going to assume you mean without domain wide delegation on the gsuite and not verification)
Service accounts dont work with gmail unless you set up domain wide delegation to a Gsuite account. The reason being is that a service account is its own user you need to delegate its permission to access your gmail account. This will only work with a gsuite domain email address.
There is no way to share / grant another user permission to access your standard gmail account. So there is no way for you go delegate the permissions for bob@mycompany.com to access bob@gmail.com.
I recommend using standard Oauth2 if this is a standard gmail account and saving the refresh token and storing it with your application it will then be able to request a new access token when ever it needs. As long as the refresh token is used regularly you should not have any issues with this solution.
https://developers.google.com/gmail/api/guides/delegate_settings