未经授权的客户端:未经授权的客户端可以使用此方法检索访问令牌

时间:2018-06-22 12:06:17

标签: python google-api google-drive-api google-oauth2

我是一名GSuite管理员,拥有近300个用户,并且正从GSuite迁移。我需要下载他们创建/上传的所有用户文件。

我从编写Python脚本开始,该脚本将向我显示列表中的用户文件,似乎让我陷入了压倒性的授权问题。

  1. 我已经在Google控制台中创建了一个项目,并创建了一个具有私钥(基于json)和GSuite域范围委托复选框的服务帐户
  2. 在“我的GSuite管理”面板中,我已在“管理API访问”中将新创建的客户端ID和权限范围添加到以下范围:https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/admin.datatransfer,https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group

根据文档(https://developers.google.com/admin-sdk/directory/v1/guides/delegation)很好!

  1. 我正在根据ServiceAccountCredentials创建资源对象,并分别基于API名称/版本“ drive”和“ v3”构建对象,并尝试根据Google的快速入门获取文件列表(https://developers.google.com/drive/api/v3/quickstart/python ):

     from googleapiclient.discovery import build
     from oauth2client.service_account import ServiceAccountCredentials
    
     SERVICE_ACCOUNT_EMAIL = "drive-getter@mygoogledomain.iam.gserviceaccount.com"
     SERVICE_ACCOUNT_PKCS12 = "./service_key.json"
    
     def create_directory_service(user_email):
       credentials = ServiceAccountCredentials.from_json_keyfile_name(SERVICE_ACCOUNT_PKCS12, scopes=['https://www.googleapis.com/auth/drive'])
       credentials = credentials.create_delegated(user_email)
    
       return build('drive', 'v3', credentials=credentials)
    
    
     resource = create_directory_service('username@mydomain.com')
    
     results = resource.files().list(
       pageSize=10, fields="nextPageToken, files(id, name)"
     ).execute()
    
     items = results.get('files', [])
    
     print(items)
    

它看起来完全正确,但我收到此错误消息:

  

已连接到pydev调试器(内部版本181.5087.37)

     

回溯(最近通话最近):文件   “ /Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py”,行   1664年,在       main()文件“ /Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py”,行   1658年,主要       globals = debugger.run(setup ['file'],None,None,is_module)文件“ /Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py”,   1068行,正在运行       pydev_imports.execfile(file,globals,locals)#执行脚本文件   “ /Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py”,   第18行,在execfile中       exec(compile(contents +“ \ n”,file,'exec'),glob,loc)文件“ /Users/probe/Projects/drive_getter/src/dconnect.py”,第16行,在          pageSize = 10,fields =“ nextPageToken,文件(id,名称)”文件“ /Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/_helpers.py”,   第130行,位于positional_wrapper中       返回包装的(* args,** kwargs)文件“ /Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/http.py”,   执行中的第835行       method = str(self.method),body = self.body,headers = self.headers)文件   “ /Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/http.py”,   _retry_request中的第162行       resp,content = http.request(uri,方法,* args,** kwargs)文件“ /Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/transport.py”,   第159行,在new_request中       凭证。_refresh(orig_request_method)文件“ /Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/client.py”,   _refresh中的第749行       self._do_refresh_request(http)文件“ /Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/client.py”,   _do_refresh_request中的第819行       引发HttpAccessTokenRefreshError(error_msg,status = resp.status)oauth2client.client.HttpAccessTokenRefreshError:未经授权的客户端:   客户端未经授权使用此方法检索访问令牌。

任何想法在此过程中做错了什么?再说一次-我的目标是列出并稍后从所有GSuite用户下载所有用户文件,因此我考虑循环我的用户电子邮件并对所有电子邮件应用相同的逻辑,直到我下载所有文件为止。

感谢您的合作!

2 个答案:

答案 0 :(得分:4)

  

未经授权,客户端无法使用此方法检索访问令牌。

Google Develoepr控制台中有几种不同类型的客户端。

  • 浏览器-用于Web应用程序。
  • 本机-用于已安装的应用程序
  • 服务帐户-用于服务器之间的通信
  • 移动

用于对这些不同类型进行身份验证的代码是可以理解的。

您使用的代码似乎是带有服务帐户的python的正确代码。尽管from_json_keyfile_name接受p12文件,而不接受.json文件。

那里的客户必须处于核心地位。返回Google开发者控制台,创建一个服务帐户客户端,并下载正确的.json文件。

Service account python

from google.oauth2 import service_account

SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'

credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

我建议在.p12文件上使用.json文件,我怀疑Google将来会在某些时候停止使用这些文件。

答案 1 :(得分:3)

解决方案很简单。

首先,据我所知,仅当您使用P12键并基于这些凭据构造对象时,google.oauth2库才支持域范围的委托功能。

第二,请注意您正在下载的p12密钥的文件名,我将密钥文件名重命名为更短的名称,并且没有注意Google在文件名本身中包含了公共密钥指纹。

因此,解决方案是,在我的问题中描述的所有步骤,使用p12密钥创建服务帐户,勾选域范围内的委派,并且工作代码如下所示:

<table border=0>
  <tr>
    <td>
      <table  id="table1" width="300" border="2" align="right" cellpadding="1" cellspacing="1">
          <tr class="tb1">
          <td>station</td>
          <td>wind</td>
          </tr>
      </table>
    </td>
  </tr>
</table>

奖金:如果您想从GDrive下载文件并保留文件夹结构(Google不会告诉您文件哈希是否为文件夹),请使用提取的mimeType和父母ID来构建父母堆栈(文件夹),然后在循环列表时自动创建它们,然后将文件放在其各自的父ID中。