Gmail API 是不是支持使用 OAuth 服务帐户?
Posted
技术标签:
【中文标题】Gmail API 是不是支持使用 OAuth 服务帐户?【英文标题】:Does the Gmail API support using OAuth Service Accounts?Gmail API 是否支持使用 OAuth 服务帐户? 【发布时间】:2015-03-04 20:13:08 【问题描述】:我正在尝试将 Gmail API 与 Python Google 客户端库一起使用。
我已通过 Google 开发者控制台创建了一个服务帐户凭据。
然后我尝试使用像 sO 这样的凭据:
from oauth2client.client import SignedJwtAssertionCredentials
client_email = '<sanitised>@developer.gserviceaccount.com'
with open("foobar-<sanitised>.p12") as f:
private_key = f.read()
credentials = SignedJwtAssertionCredentials(client_email, private_key, 'https://www.googleapis.com/auth/gmail.readonly')
from httplib2 import Http
http_auth = credentials.authorize(Http())
from apiclient.discovery import build
gmail_server = build('gmail', 'v1', http=http_auth)
但是,当我尝试使用实际的 Gmail API 时,我收到了 HTTP 500 错误:
In [13]: threads = gmail_server.users().threads().list(userId='me').execute()
---------------------------------------------------------------------------
HttpError Traceback (most recent call last)
<ipython-input-13-a74134635cc3> in <module>()
----> 1 threads = gmail_server.users().threads().list(userId='me').execute()
/Users/victorhooi/.virtualenvs/kenny/lib/python2.7/site-packages/oauth2client/util.pyc in positional_wrapper(*args, **kwargs)
133 else: # IGNORE
134 pass
--> 135 return wrapped(*args, **kwargs)
136 return positional_wrapper
137
/Users/victorhooi/.virtualenvs/kenny/lib/python2.7/site-packages/googleapiclient/http.pyc in execute(self, http, num_retries)
721 callback(resp)
722 if resp.status >= 300:
--> 723 raise HttpError(resp, content, uri=self.uri)
724 return self.postproc(resp, content)
725
HttpError: <HttpError 500 when requesting https://www.googleapis.com/gmail/v1/users/me/threads?alt=json returned "Backend Error">
这里的一位用户提到,“服务帐户”显然不支持使用 GMail API:
https://***.com/a/24645874/139137
是否有人能够确认是否是这种情况,或者 Google 是否在任何地方记录了这种情况?
我的假设是,由于服务帐户凭据是通过用户的 Google 开发者控制台创建的,它只会与该用户相关联,并且应该可以正常工作吗?
编辑:
我还应该提到我确实尝试将我的客户端显式添加到 Google Apps 管理控制台中的“管理客户端 API 访问”页面:
但是,我仍然收到 HTTP 500 后端错误。
此外,该页面上的帮助链接指向 OAuth 1.0 特定页面 - 我怀疑该页面仅适用于 OAuth 1.0,尽管此处没有明确提及。
编辑 2
另外,我应该提到我尝试在以下位置使用 Google API Explorer:
https://developers.google.com/apis-explorer/#p/gmail/v1/gmail.users.messages.list?userId=me&_h=1&
使用 OAuth 2.0 和交互式用户流程,它运行良好(即它列出了电子邮件)。
编辑 3
我尝试按照 Jay Lee 的建议添加 sub
参数。
在我自己的 Google Apps 域中,它确实有效:
from oauth2client.client import SignedJwtAssertionCredentials
client_email = '<sanitised>@developer.gserviceaccount.com'
with open('foo-bar-<sanitised>.p12') as f:
private_key = f.read()
credentials = SignedJwtAssertionCredentials(client_email, private_key, 'https://www.googleapis.com/auth/gmail.readonly', sub='victorhooi@example.com')
from httplib2 import Http
http_auth = credentials.authorize(Http())
from apiclient.discovery import build
gmail_server = build('gmail', 'v1', http=http_auth)
threads = gmail_server.users().threads().list(userId='me').execute()
然后线程给了我:
In [12]: threads
Out[12]:
u'nextPageToken': u'00058094761552980977',
u'resultSizeEstimate': 178,
u'threads': [u'historyId': u'8942',
u'id': u'14abc26f1893823b',
u'snippet': u'',
u'historyId': u'8822', u'id': u'14a4ffc2724e9384', u'snippet': u'',
u'historyId': u'8769', u'id': u'14a36a9c6f552af3', u'snippet': u'',
u'historyId': u'8716', u'id': u'14a31822f19bb161', u'snippet': u'',
u'historyId': u'8671', u'id': u'14a2bee13eb87c07', u'snippet': u'',
但是,当我尝试在我的公司 Google Apps 域上使用 sub 参数时,当我到达以下行时:
gmail_server = build('gmail', 'v1', http=http_auth)
这给了我错误:
AccessTokenRefreshError: access_denied: Requested client not authorized.
我相当确定客户端确实存在于 Google 开发者的控制台中,并且启用了 Gmail API。我只是不确定为什么 sub
参数会触发该错误。
然后,如果我在公司 Google Apps 域中使用其他帐户尝试相同的代码,但尚未委托,我会得到:
AccessTokenRefreshError: unauthorized_client: Unauthorized client or scope in request.
【问题讨论】:
【参考方案1】:尝试使用:
credentials = SignedJwtAssertionCredentials(client_email, private_key,
'https://www.googleapis.com/auth/gmail.readonly', sub='user@domain.com')
其中 user@domain.com 是您要模拟的用户。
【讨论】:
感谢您的建议。我确实尝试过(参见上面的编辑 3),但是,当我添加它时,它给了我一个不同的错误消息(“AccessTokenRefreshError:access_denied:请求的客户端未授权。”) 您需要授予该服务帐户对您的工作域的访问权限:developers.google.com/admin-sdk/directory/v1/guides/… 在授予您在代码中请求的权限时,请确保使用相同的范围。以上是关于Gmail API 是不是支持使用 OAuth 服务帐户?的主要内容,如果未能解决你的问题,请参考以下文章
访问未授予或过期 GMAIL API 和 Oauth2 / 如何使用 GMAIL API 和 GSuite 域设置电子邮件签名
Gmail API - Oauth2/google:找不到凭据(Golang)
通过服务器端的服务帐户使用 gmail api,避免使用 OAUTH2 GUI