Google API 服务帐户。即使使用域范围委派访问,也只能看到服务帐户驱动器

Google API Service Account. Can only see service accounts drive even with Domain Wide Delegation Access

我目前正在使用 Google 服务帐户,该帐户启用了全域委派(我遵循了此 link https://developers.google.com/identity/protocols/oauth2/service-account, and this link https://developers.google.com/admin-sdk/reports/v1/guides/delegation),并且具有 "https: //www.googleapis.com/auth/drive scope enabled. 我已经下载了服务帐户的 json 凭据并将它们放在与我的 python 脚本相同的目录中. 问题是当我在我的域中模拟另一个用户假设 User2 时,我尝试列出 User2 驱动器中的文件。我只得到我服务帐户驱动器中的文件。

我有一段模拟 User2 的代码。

def auth():
    domain = 'domain'
    # impersonate this user
    user = 'testuser' # id only (ie. without @domain)
    #scopes = ['https://www.googleapis.com/auth/drive',]
    key_file = 'service_account.json'

    subject = ''.join([user,'@',domain])
    delegated_credentials = service_account.Credentials.from_service_account_file(key_file)
    delegated_credentials.with_subject(subject)
    drive_service = googleapiclient.discovery.build('drive', 'v2', credentials=delegated_credentials)

    return drive_service

然后我试图获取用户 mydrive 中的文件列表。

children = service.children().list(folderId='root', **param).execute()

for child in children.get('items', []):
    item = service.files().get(fileId=child['id']).execute()

以上项目始终是服务帐户我的驱动器中的“入门 PDF”

基本上,这样做的全部目的是以编程方式将任何文件夹(及其内容)的所有权更改为同一 G-Suite 中的其他用户。

此外,我不想像许多其他帖子所说的那样与我的服务帐户共享文件夹。这不应该是我冒充所有者的情况。

答案:

您的身份验证流程存在两个问题:缺少范围和错误分配的变量。

更多信息:

  1. 分配 delegated_credentials 变量时,您的委托凭据缺少范围。
  2. 您在添加主题时并未分配新委派的凭据。

正如您在 Preparing to make an authorized API call 文档中看到的那样,在定义 credentials 对象时 您必须 指定您将在请求中使用哪些范围。

然后,在将范围添加到凭据时,您需要将其分配给一个变量,该变量可以传递给 Drive 服务的构建。

代码修复:

要修复第 1 点,您需要取消对范围的注释并更改此行:

delegated_credentials = service_account.Credentials.from_service_account_file(key_file)

包括以下范围:

scopes = ['https://www.googleapis.com/auth/drive']
delegated_credentials = service_account.Credentials.from_service_account_file(
        key_file, scopes=scopes)

此外,在构建驱动服务之前,您需要将 delegated_credentials.with_subject(subject) 分配给自身:

delegated_credentials = delegated_credentials.with_subject(subject)
drive_service = googleapiclient.discovery.build(
        'drive', 'v2', credentials=delegated_credentials)

参考文献: