GSuite Api 访问:客户端无权使用此方法检索访问令牌

GSuite Api Access: Client is unauthorized to retrieve access tokens using this method

我正在尝试通过 python 脚本为我的组织访问存储在 Google 驱动器中的文档。

这是我所做的:

  1. 创建了一个新的服务帐户并选择了 "Enable G Suite Domain-wide Delegation"
  2. 然后我进入我帐户的 GSuite 管理员并通过安全 -> 高级设置 -> 管理 API 客户端访问我添加了为我的新服务帐户生成的客户端 ID 和这些权限 as detailed here :

然后我有以下 python 方法来构建访问 gsuite 文档的服务:

def get_service(api_name, api_version, scopes, key_file_location):
    """Get a service that communicates to a Google API.

    Args:
        api_name: The name of the api to connect to.
        api_version: The api version to connect to.
        scopes: A list auth scopes to authorize for the application.
        key_file_location: The path to a valid service account JSON key file.

    Returns:
        A service that is connected to the specified API.
    """

    # credentials = ServiceAccountCredentials.from_json_keyfile_name(
    #         key_file_location, scopes=scopes)
    credentials = service_account.Credentials.from_service_account_file(
        key_file_location, scopes=scopes)

    delegated_credentials = credentials.with_subject('myemail@my-gsuite-domain.com')

    # Build the service object.
    service = build(api_name, api_version, credentials=delegated_credentials)

    return service

当我尝试访问电子表格时出现以下错误:

('unauthorized_client: Client is unauthorized to retrieve access tokens using this method.', u'{\n "error": "unauthorized_client",\n "error_description": "Client is unauthorized to retrieve access tokens using this method."\n}')

该电子表格拥有组织中任何人都可以查看的权限。

我还尝试手动将服务帐户电子邮件地址添加到电子表格权限中,这样我就可以在不使用委托凭据的情况下访问文档,但我想避免必须将电子邮件地址添加到每个电子表格中我要访问

如何以编程方式查看组织成员使用 Python 可查看的所有 Google 工作表?

谢谢。

感谢@AChampion 指点。当我只授权范围 https://www.googleapis.com/auth/spreadsheets 时,问题竟然是请求范围 https://www.googleapis.com/auth/spreadsheets.readonly。我认为 spreadsheets 会是 spreadsheets.readonly 的超集,但事实并非如此。

我的get_service代码:

def get_service(api_name, api_version, scopes, key_file_location):
    """Get a service that communicates to a Google API.

    Args:
        api_name: The name of the api to connect to.
        api_version: The api version to connect to.
        scopes: A list auth scopes to authorize for the application.
        key_file_location: The path to a valid service account JSON key file.

    Returns:
        A service that is connected to the specified API.
    """

    credentials = ServiceAccountCredentials.from_json_keyfile_name(
            key_file_location, scopes=scopes)
    # credentials = service_account.Credentials.from_service_account_file(
    #     key_file_location, scopes=scopes)

    delegated_credentials = credentials.create_delegated('name@example.com')  
    delegated_http = delegated_credentials.authorize(Http())

    # Build the service object.
    service = build(api_name, api_version, http=delegated_http)

    return service

还有我给 get_service 的电话:

scope = 'https://www.googleapis.com/auth/spreadsheets'
key_file_location = '/path/to/keyfile.json'
service = get_service(
            api_name='sheets',
            api_version='v4',
            scopes=[scope],
            key_file_location=key_file_location)