AccessTokenRefreshError:带有App Engine App的oAuth 2.0服务帐户的Google电子表格API

2024-06-28 19:34:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过gdataapi访问Google电子表格,使用oauth2.0服务帐户凭证为googleappengine上托管的python2.7应用创建。在

  1. 该应用程序使用了Google最新的gdatapython客户端,v.2.0.18(gdata和atom)。在
  2. 该应用程序使用了最新的googleapi python客户端gae,v.1.2。在
  3. 在这个项目的googledeveloper控制台中(在本例中称为“mygae app”),我创建了一个服务帐户并将整个域的权限委托给服务帐户as described here
  4. Google Drive中所需的电子表格属于Google Apps for Work域,此处称为“mygoogleappsdomain.com网站". 在
  5. 我已将电子表格的读写权限授予my-gae-app@appspot.gserviceaccount.com和为此服务帐户显示的电子邮件地址,该地址在下面的代码中被分配给clientEmail变量。我不确定这两个电子邮件地址中的哪一个是实际需要的,所以我都分配了。{用户还可以使用此cd3}写入电子表格。在

使用googleapi Python客户机的AppAssertionCredentials我可以通过googledriveapi访问所需电子表格的元数据。但是,如果我试图使用gdata访问电子表格的内容,就会出错。到目前为止,使用服务帐户的最好结果是使用SignedJwtAssertionCredentialsas suggested here。然而,我被困在这个AccessRefreshTokenError: access denied中,我不知道出了什么问题。在

import os
import httplib2
from google.appengine.api import memcache
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
import gdata.spreadsheets.client
import gdata.spreadsheet.service

# AppAssertionCredentials is not supported in gdata python client library,
# so we use SignedJwtAssertionCredentials with the credential 
# file of this service account.
# Load the key in PKCS 12 format that you downloaded from the Google API
# Console when you created your Service account.
clientEmail = '10346........-g3dp......................3m1em8@developer.gserviceaccount.com'
p12File = 'app.p12'
path = os.path.join(ROOT_DIR, 'data', 'oAuth2', p12File)
impersonateUser = 'user@mygoogleappsdomain.com'
spreadsheetKey = '1mcJHJ...................................juQMw' # ID copied from URL of desired spreadsheet in Google Drive
with open(path) as f:
    privateKey = f.read()
    f.close()

# Getting credentials with AppAssertionCredentials only worked successfully
# for Google API Client Library for Python, e.g. accessing file's meta-data.
# So we use SignedJwtAssertionCredentials, as suggested in
# https://stackoverflow.com/questions/16026286/using-oauth2-with-service-account-on-gdata-in-python
credentials = SignedJwtAssertionCredentials(
    clientEmail,
    privateKey,
    scope=(
        'https://www.googleapis.com/auth/drive.file ',
        # added the scope above as suggested somewhere else,
        # but error occurs with and with-out this scope
        'https://www.googleapis.com/auth/drive',
        'https://spreadsheets.google.com/feeds',
        'https://docs.google.com/feeds'
    ),
    sub=impersonateUser
)

http = httplib2.Http()
http = credentials.authorize(http)
auth2token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
# error will occur, wether using SpreadsheetsService() or SpreadsheetsClient()
#srv = gdata.spreadsheet.service.SpreadsheetsService()
#srv = auth2token.authorize(srv)

clt = gdata.spreadsheets.client.SpreadsheetsClient()
clt = auth2token.authorize(clt)
# Until here no errors

wks = clt.get_worksheets(spreadsheetKey)
# AccessTokenRefreshError: access_denied

这是我在远程shell中遇到的错误:

^{pr2}$

我不确定这是否表示拒绝此服务帐户访问电子表格,或者刷新访问令牌时出错。你知道这个代码或设置有什么问题吗?在


Tags: infromhttpsimportcomclientasservice
1条回答
网友
1楼 · 发布于 2024-06-28 19:34:08

我发现在没有sub参数的情况下调用SignedJwtAssertionCredentials(对于“模拟的”用户)不会产生AccessTokenRefreshError: access_denied

import os
import httplib2
from google.appengine.api import memcache
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
import gdata.spreadsheets.client
import gdata.spreadsheet.service

# AppAssertionCredentials is not supported in gdata python client library,
# so we use SignedJwtAssertionCredentials with the credential 
# file of this service account.
# Load the key in PKCS 12 format that you downloaded from the Google API
# Console when you created your Service account.
clientEmail = '10346........-g3dp......................3m1em8@developer.gserviceaccount.com'
p12File = 'app.p12'
path = os.path.join(ROOT_DIR, 'data', 'oAuth2', p12File)
impersonateUser = 'user@mygoogleappsdomain.com'
spreadsheetKey = '1mcJHJ...................................juQMw' # ID copied from URL of desired spreadsheet in Google Drive
with open(path) as f:
    privateKey = f.read()
    f.close()

# Getting credentials with AppAssertionCredentials only worked successfully
# for Google API Client Library for Python, e.g. accessing file's meta-data.
# So we use SignedJwtAssertionCredentials, as suggested in
# http://stackoverflow.com/questions/16026286/using-oauth2-with-service-account-on-gdata-in-python
# but with-out the sub parameter!
credentials = SignedJwtAssertionCredentials(
    clientEmail,
    privateKey,
    scope=(
        'https://www.googleapis.com/auth/drive.file ',
        # added the scope above as suggested somewhere else,
        # but error occurs with and with-out this scope
        'https://www.googleapis.com/auth/drive',
        'https://spreadsheets.google.com/feeds',
        'https://docs.google.com/feeds'
    ),
#    sub=impersonateUser
)

http = httplib2.Http()
http = credentials.authorize(http)
auth2token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
# this pattern would eventually also work using SpreadsheetsService()
# SpreadsheetsService methods are different from SpreadsheetsClient, though
#srv = gdata.spreadsheet.service.SpreadsheetsService()
#srv = auth2token.authorize(srv)

clt = gdata.spreadsheets.client.SpreadsheetsClient()
clt = auth2token.authorize(clt)

wks = clt.get_worksheets(spreadsheetKey)
# works now!

相关问题 更多 >