Google-api-python-client: google.auth.exceptions.RefreshError using delegated credentials

Created on 11 Jan 2019  路  10Comments  路  Source: googleapis/google-api-python-client

Hi,

I'm trying to use the Google API client to retrieve email for a user using a service account. I've created the service account credentials with a role of Project Owner, and with domain-wide delegation enabled. However, when I try to connect as a particular user I get:

Traceback (most recent call last):
  File "gmail.py", line 43, in <module>
    messages = ListMessages(service, '[email protected]')
  File "gmail.py", line 22, in ListMessages
    response = service.users().messages().list(userId=user).execute()
  File "/home/ubuntu/.local/lib/python2.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/googleapiclient/http.py", line 846, in execute
    method=str(self.method), body=self.body, headers=self.headers)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/googleapiclient/http.py", line 164, in _retry_request
    resp, content = http.request(uri, method, *args, **kwargs)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/google_auth_httplib2.py", line 187, in request
    self._request, method, uri, request_headers)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/google/auth/credentials.py", line 122, in before_request
    self.refresh(request)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/google/oauth2/service_account.py", line 322, in refresh
    request, self._token_uri, assertion)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/google/oauth2/_client.py", line 145, in jwt_grant
    response_data = _token_endpoint_request(request, token_uri, body)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/google/oauth2/_client.py", line 111, in _token_endpoint_request
    _handle_error_response(response_body)
  File "/home/ubuntu/.local/lib/python2.7/site-packages/google/oauth2/_client.py", line 61, in _handle_error_response
    error_details, response_body)
google.auth.exceptions.RefreshError: ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method.', u'{\n  "error": "unauthorized_client",\n  "error_description": "Client is unauthorized to retrieve access tokens using this method."\n}')
 ```

In terms of software versions I have:

google-api-python-client (1.7.7)
google-auth (1.6.2)
google-auth-httplib2 (0.0.3)

Here's the code I'm using:

from google.oauth2 import service_account
import googleapiclient.discovery

SCOPES = ['https://www.googleapis.com/auth/gmail.modify']
SERVICE_ACCOUNT_FILE = 'service-account.json'

def ListMessages(service, user):

    response = service.users().messages().list(userId=user).execute()
    messages = response['messages']

    while 'nextPageToken' in response:
            page_token = response['nextPageToken']
            response = service.users().messages().list(userId=user, pageToken=page_token).execute()
            messages.extend(response['messages'])

    return messages

if __name__ == "__main__":
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject('[email protected]')
service = googleapiclient.discovery.build('gmail', 'v1', credentials=delegated_credentials)

    messages = ListMessages(service, '[email protected]')

```

Any help appreciated.

Thanks, Tom

docs

Most helpful comment

I've discovered that credentials.token is empty and credentials.valid is False. Looks like there are additional steps needed to authorize the credentials? I'm following https://developers.google.com/api-client-library/python/auth/service-accounts and https://developers.google.com/gmail/api/quickstart/python for the GMail API portion but don't see any steps to authorize beyond what I'm doing above.

All 10 comments

I've discovered that credentials.token is empty and credentials.valid is False. Looks like there are additional steps needed to authorize the credentials? I'm following https://developers.google.com/api-client-library/python/auth/service-accounts and https://developers.google.com/gmail/api/quickstart/python for the GMail API portion but don't see any steps to authorize beyond what I'm doing above.

@mthaddon That looks correct. Since you are getting an unauthorized_client error, I would double check the steps here: https://developers.google.com/api-client-library/python/auth/service-accounts#delegatingauthority

@busunkim96 thanks - I am following the instructions on that page as closely as I can. Is there any way of getting more detailed information about what specifically is failing? As I mentioned I've set up the service account and given it domain-wide delegation.

The page you mentioned says "Select Manage third party OAuth Client access in the Authentication section", but all I see is "Manage API client access". Assuming this was the same thing, I set up an authorized api client for the service account I'd created with a scope of "Email (Read/Write) https://www.googleapis.com/auth/gmail.modify". In my script as you can see above this is the only scope I'm using. Is that correct?

Unfortunately I don't think it's possible to get more details for this error. There's a similar issue filed in the Ruby repository that might be helpful for troubleshooting. If those solutions doesn't work for you, please do let us know. https://github.com/googleapis/google-auth-library-ruby/issues/123

I was able to get this working, thanks. The fix was to delete any non-service-account credentials for this account (I'd set up some oauth credentials as well). Is there somewhere I could propose a doc update to clarify this?

If you have additional suggestions we'd be happy to see those here. I'll be creating an internal issue to improve the documentation.

@mthaddon

I was able to get this working, thanks. The fix was to delete any non-service-account credentials for this account (I'd set up some oauth credentials as well). Is there somewhere I could propose a doc update to clarify this?

Unfortunately it still doesn't work for me. Full description of my exact issue can be found here

Any idea?

I found this to be a Roles issue.

  1. In your Developers Console -> Project -> IAM ensure that your service account is listed there.

    • if it isn't, click Add and start typing the name to add it

  2. For Role, select Access Approval -> Access Approval Approver

This allowed me to query any domain user's calendar event list.

I was able to get this working, thanks. The fix was to delete any non-service-account credentials for this account (I'd set up some oauth credentials as well). Is there somewhere I could propose a doc update to clarify this?

@mthaddon Could you elaborate on what you mean by non-service account credentials please? Where, in G-Suite or in the gmail account which has the service account?

Tried adding what @vancityhuddy recommended, doesn't seem to make a difference, is this necessary?

Greetings, we're closing this. Looks like the issue got resolved. Please let us know if the issue needs to be reopened.

Was this page helpful?
0 / 5 - 0 ratings