5

I have been trying to get the Service Account authentication working for the Google Admin SDK for a few days now to no avail. I am using the google-api-python-client-1.2 library freshly installed from Google.

I have been following Google's documentation on the topic. Links are here:

htps://developers.google.com/accounts/docs/OAuth2ServiceAccount

htps://developers.google.com/api-client-library/python/guide/aaa_oauth

htp://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.client.SignedJwtAssertionCredentials-class.html

And have the tasks.py Service Account example working which you can be found here:

htp://code.google.com/p/google-api-python-client/source/browse/samples/service_account/tasks.py?r=c21573904a2df1334d13b4380f63463c94c8d0e8

And have been closely studying these two Stack Overflow threads on a related topic here:

google admin sdk directory api 403 python

Google Admin API using Oauth2 for a Service Account (Education Edition) - 403 Error

And have studied the relevant code in gam.py (Dito GAM).

Yet I'm still missing something as I am getting an 'oauth2client.client.AccessTokenRefreshError: access_denied' exception in nearly every test case I write.

Here is a concise example of a test authentication:

import httplib2
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials

f = file('myKey.p12', 'rb')
key = f.read()
f.close()

credentials = SignedJwtAssertionCredentials(
    'myServiceAdmin@developer.gserviceaccount.com', 
    key,
    sub='myAdminUser@my.googleDomain.edu', 
    scope = ['https://www.googleapis.com/auth/admin.directory.user',])

http = httplib2.Http()
http = credentials.authorize(http)
service = build('admin', 'directory_v1', http=http)

When I run the above code I get this stack dump and exception:

Traceback (most recent call last):
  File "./test.py", line 17, in <module>
    service = build('admin', 'directory_v1', http=http)
  File "/usr/lib/python2.7/dist-packages/oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/apiclient/discovery.py", line 192, in build resp, content = http.request(requested_url)
  File "/usr/lib/python2.7/dist-packages/oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/oauth2client/client.py", line 475, in new_request
    self._refresh(request_orig)
  File "/usr/lib/python2.7/dist-packages/oauth2client/client.py", line 653, in _refresh
    self._do_refresh_request(http_request)
  File "/usr/lib/python2.7/dist-packages/oauth2client/client.py", line 710, in _do_refresh_request
    raise AccessTokenRefreshError(error_msg)
oauth2client.client.AccessTokenRefreshError: access_denied

I've tried multiple super user accounts, service accounts, and keys and always end up with the same exception. If I add sub to the tasks.py example I end up with the same error. Replacing sub with prn also generates this exception and adding private_key_password='notasecret' does nothing (it is the default). The Admin SDK is activated in the Google Developers Console and the target accounts have super user privileges. This makes me think something is missing on the Google domain side but I cannot think of anything else to check.

Any one have an idea what I am doing wrong?

Community
  • 1
  • 1

2 Answers2

1

Have you granted the third party client access in your Admin Console for your service account?

My to go instruction when it comes to setting up Service Account is the instruction Google has for Drive Api.

https://developers.google.com/drive/web/delegation

Take a look at the "Delegate domain-wide authority to your service account" part and see if you have completed those steps.

Emily
  • 1,464
  • 1
  • 9
  • 12
  • Thank you Emily! You are correct, I missed the bit about setting up the API client access security. Thanks for answering my question so quickly! – user3388615 Mar 06 '14 at 17:36
  • Hi, I have a personal email account under which I created a service account. How do I "Delegate domain-wide authority to your service account"? I did not understand from the "Go to your Google Apps domain’s Admin console." I do not have any Google Apps access. I am trying use a service account with the calendar API – John May 15 '14 at 10:08
0

Maybe not OP's problem, but I had this same error and my issue was that I was setting the sub field in the credentials object

credentials = SignedJwtAssertionCredentials(SERVICE_ACCOUNT_EMAIL, key,
      scope=SCOPES, sub=**<DON'T SET ME>**)

If you're using domain-wide delegation, you need to not set a sub (because your "user" is the domain administrator.) The docs are a bit confusing on this point. I just removed the sub field and it worked for me.

rogueleaderr
  • 4,671
  • 2
  • 33
  • 40