api - 在 oAuth Google Api Flow 中使用 "create_delegated"时遇到问题....gDrive

标签 api google-api google-drive-api

问题的症结在于,运行以下命令时,我无法委派凭据在其他用户帐户中工作。唯一的在线示例是使用 JSON 服务帐户,而不是 oAuth 身份验证流程。

newcreds = creds.create_delegated('<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5f00002b3a2c2b2a2c3a2d2c3a3e2d3c3700001f383b3a29713d3c713a3b2a" rel="noreferrer noopener nofollow">[email protected]</a>')
AttributeError: 'Credentials' object has no attribute 'create_delegated'

我的代码的亮点如下,正常的凭据登录效果很好,但需要访问其他用户帐户......

#!/usr/bin/env python
from __future__ import print_function
import pickle
import os.path
import json
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

import sys

print('test')
##VARS
SCOPES = ['https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/admin.directory.user']
creds = None
count = 0
##Google Creds
creds = None
if os.path.exists(os.path.dirname(os.path.abspath(__file__))+'/secrets/token.pickle'):
    with open(os.path.dirname(os.path.abspath(__file__))+'/secrets/token.pickle', 'rb') as token:
        creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
            os.path.dirname(os.path.abspath(__file__))+'/secrets/credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    # Save the credentials for the next run
    with open(os.path.dirname(os.path.abspath(__file__))+'/secrets/token.pickle', 'wb') as token:
        pickle.dump(creds, token)

newcreds = creds.create_delegated('<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e4bbbb908197909197819697818596878cbbbba485808096819797ca808b89858d8a" rel="noreferrer noopener nofollow">[email protected]</a>')

service = build('drive', 'v3', credentials=creds)

最佳答案

使用 Google-OAuth 2.0 管理用户

管理 GSuite 域用户必须分为两部分

  1. Admin SDK创建用户、检索用户、更新用户等方法(基本上是管理员可以在 admin console 中执行的所有操作)在使用其凭据进行身份验证时可以由域管理员直接访问

  2. GSuite 管理员无法直接访问涉及使用大多数其他 API(Drive API、Gmail API 等)和访问私有(private)用户数据的方法。

出于安全原因,后者必须通过 service account 执行.

  • 创建(或更新)服务帐户时,管理员可以决定授予其哪些范围并执行 domain-wide delegation .
  • 域范围委派意味着服务帐户可以代表域用户 impersonating他 - 即充当用户并获得与用户本人相同的用户数据访问权限。
  • 使用服务帐户的身份验证流程与常见的 Google API 身份验证不同。
  • 没有以相同的方式创建访问或刷新 token ,并且管理员的工作目录中没有存储 token.json 文件。
  • 相反,在 GCP 控制台中创建服务帐号时,需要将服务帐号凭据作为 jsonp12 文件下载到工作目录。<
  • 对于使用 Python 定义的 json 凭据文件模拟的服务帐户:
from google.oauth2 import service_account

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

credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject('<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a3d6d0c6d1e3c6dbc2ced3cfc68dccd1c4" rel="noreferrer noopener nofollow">[email protected]</a>')
drive_service = googleapiclient.discovery.build(
        'drive', 'v3', credentials=delegated_credentials)

with_subject 是使服务模拟用户的关键部分。

指定的范围必须与您在管理控制台中分配给服务帐号的范围一致。

使用服务帐号时,去掉正常认证的代码部分,即

    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)

其他信息

如果您更喜欢使用 p12 凭据文件而不是 json,则 with_subject 将通过 create_delegate 替换.

示例:

from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials

# Email of the Service Account
SERVICE_ACCOUNT_EMAIL = 'YOUR SERVICE ACCOUNT EMAIL'

# Path to the Service Account's Private Key file
SERVICE_ACCOUNT_PKCS12_FILE_PATH = '/path/to/<public_key_fingerprint>-privatekey.p12'

def create_directory_service(user_email):
    """Build and returns an Admin SDK Directory service object authorized with the service accounts
    that act on behalf of the given user.

    Args:
      user_email: The email of the user. Needs permissions to access the Admin APIs.
    Returns:
      Admin SDK directory service object.
    """

    credentials = ServiceAccountCredentials.from_p12_keyfile(
        SERVICE_ACCOUNT_EMAIL,
        SERVICE_ACCOUNT_PKCS12_FILE_PATH,
        'notasecret',
        scopes=['https://www.googleapis.com/auth/drive'])

    credentials = credentials.create_delegated(user_email)

    return build('drive', 'v3', credentials=credentials)

关于api - 在 oAuth Google Api Flow 中使用 "create_delegated"时遇到问题....gDrive,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62045825/

相关文章:

PHP Paypal API ExpressCheckout,我不知道我在历史细节中卖了什么

google-drive-api - 提高每个用户的 Google Drive API 限制并不能阻止速率限制异常

java - Google drive rest API,仅从根文件夹下载文件

javascript - 我怎样才能让我的谷歌地图动画化,让它无休止地向右平移?

java - 通过输入流将字节流上传到 Google Drive

google-drive-api - 没有 Oauth 的 Google Drive API 和接收文件

java - MagicDraw 有 Python 接口(interface)或 API 包装器吗?

ruby-on-rails - 使用嵌套参数从 Node js 到 ruby​​ on Rails 的 http post

php - 使用 Instagram API 本地登录

php - google-api-php-client-0.5.0 回调网址?