使用Oauth2作为服务帐户(教育版)的Google Python Admin SDK - “oauth2client.client.AccessTokenRefreshError:access_denied”异常

时间:2014-03-06 16:39:56

标签: python-2.7 oauth google-admin-sdk google-api-python-client

我一直试图让Google Admin SDK的服务帐户身份验证工作几天,但无济于事。我正在使用谷歌新安装的google-api-python-client-1.2库。

我一直在关注该主题的Google文档。链接在这里:

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

让tasks.py服务帐户示例正常工作,您可以在此处找到:

HTP://code.google.com/p/google-api-python-client/source/browse/samples/service_account/tasks.py R = c21573904a2df1334d13b4380f63463c94c8d0e8

在这里一直在仔细研究这两个相关主题的Stack Overflow线程:

google admin sdk directory api 403 python

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

并研究过gam.py(Dito GAM)中的相关代码。

然而,我仍然遗漏了一些东西,因为我在几乎每个我写的测试用例中都得到了'oauth2client.client.AccessTokenRefreshError:access_denied'异常。

以下是测试身份验证的简明示例:

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)

当我运行上面的代码时,我得到了这个堆栈转储和异常:

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

我尝试过多个超级用户帐户,服务帐户和密钥,但最终会遇到相同的异常。如果我在tasks.py示例中添加sub,我最终会遇到相同的错误。用prn替换sub也会生成此异常,并且添加private_key_password ='notasecret'不会执行任何操作(这是默认设置)。 Admin SDK在Google Developers Console中激活,目标帐户具有超级用户权限。这让我觉得谷歌领域缺少一些东西,但我想不出其他任何事情要检查。

任何人都知道我做错了什么?

2 个答案:

答案 0 :(得分:1)

您是否已在管理控制台中为您的服务帐户授予第三方客户端访问权限?

我在设置服务帐户时的说明是Google对Drive Api的指示。

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

查看“将域范围的权限委派给您的服务帐户”部分,看看您是否已完成这些步骤。

答案 1 :(得分:0)

也许不是OP的问题,但我有同样的错误,我的问题是我在凭证对象中设置子字段

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

如果您正在使用域范围的委派,则无需设置子目录(因为您的“用户”是域管理员。)文档在这一点上有点令人困惑。我刚删除了子字段,它对我有用。