unauthorized_client: клиент не авторизован для получения токенов доступа с помощью этого метода

1

Я администратор GSuite с почти 300 пользователями, и я ухожу от GSuite. Мне нужно загрузить все наши пользовательские файлы, которые они создали/загрузили.

Я начинаю с малого с написания сценария Python, который покажет мне пользовательские файлы в списке, и похоже, что я застрял в подавляющих проблемах с авторизацией.

  1. Я создал проект в Google Консоли и создал флажок "Учетная запись службы с закрытым ключом (json based) и GSuite для домена"
  2. В моей панели администрирования GSuite я добавил вновь созданный идентификатор клиента и область разрешений в Manage API для доступа к этим областям: 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 = "[email protected]"
     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('[email protected]')
    
     results = resource.files().list(
       pageSize=10, fields="nextPageToken, files(id, name)"
     ).execute()
    
     items = results.get('files', [])
    
     print(items)
    

Это выглядит совершенно правильно, но я получаю сообщение об ошибке:

Подключен к отладчику pydev (сборка 181.5087.37)

Traceback (последний последний вызов): Файл "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py", строка 1664, в главном() файле "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py ", строка 1658, в главных глобалах = debugger.run(setup ['file'], None, None, is_module) Файл"/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py ", строка 1068, в run pydev_imports.execfile (файл, globals, locals) # выполнить скрипт Файл "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", строка 18, в execfile exec (компиляция ([ CN10] "\n", файл, 'exec'), glob, loc) Файл "/Users/probe/Projects/drive_getter/src/dconnect.py", строка 16, в pageSize = 10, fields = "nextPageToken, файлы (id, name) "Файл"/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/_helpers.py ", строка 130, в positional_wrapper return wrapped (* args, ** kwargs ) Файл "/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/http.py", строка 835, в методе execute = str (self.method), body = self.body, headers = self.headers) Файл "/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/http. py ", строка 162, в _retry_request resp, content = http.request(uri, method, * args, ** kwargs) Файл"/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/transport.py ", строка 159, в new_request credentials._refresh (orig_request_method) Файл"/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/client.py ", строка 749, в _refresh self._do_refresh_request (http) Файл "/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/client.py", строка 819, в _do_refresh_request повысит HttpAccessTokenRefreshError (error_msg, status = resp.status) oauth2client.client.HttpAccessTokenRefreshError: unauthorized_client: клиент неавторизован для получения токенов доступа с использованием этого метода.

Любая идея, что было сделано неправильно в этом процессе? Опять же: моя цель состоит в том, чтобы перечислить и загрузить все пользовательские файлы со всех пользователей GSuite, поэтому я думал о том, чтобы зацикливать мои электронные письма пользователей и применять одну и ту же логику для всех, пока не получаю все загруженные файлы.

Спасибо за сотрудничество!

Теги:
google-api
google-drive-sdk
google-oauth2

2 ответа

2
Лучший ответ

Решение было простым.

Прежде всего, для того, что я мог найти, библиотека google.oauth2 поддерживает функции делегирования домена только в том случае, если вы используете ключ P12 и строите объект на основе этих учетных данных.

Во-вторых, обратите внимание на имя файла p12, который вы загружаете, я переименовал ключевое имя файла на что-то более короткое и не обратил внимания на то, что Google включает в себя открытый отпечаток пальца в самом имени файла.

Таким образом, решение состоит в том, что все шаги, описанные в моем сообщении вопроса, создают учетную запись службы с ключом p12, делегируют доменное доменное имя и рабочий код будет выглядеть так:

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

SERVICE_ACCOUNT_EMAIL = "[email protected]"
PK12_FILE = "./private-key-original-filename.p12"
PK12_PASSWORD = "notasecret"
SCOPES = ['https://www.googleapis.com/auth/drive']

def create_directory_service(user_email):
    credentials = ServiceAccountCredentials.from_p12_keyfile(
        SERVICE_ACCOUNT_EMAIL,
        PK12_FILE,
        PK12_PASSWORD,
        scopes=SCOPES
    )

    credentials = credentials.create_delegated(user_email)

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


bryan = create_directory_service('[email protected]')

results = bryan.files().list(
    pageSize=10, fields="nextPageToken, files(id, name, mimeType, parents)"
).execute()

items = results.get('files', [])

print(items)

Бонус: если вы когда-либо захотите загрузить файлы из GDrive и сохранить структуру папок (Google не сообщает вам, является ли хеш файл файловой системой или нет), используйте mimeType извлеченный и родительский ID для создания стека родителей (папок), создайте их автоматически, зацикливая свой список, а затем поместите файлы в их соответствующий родительский идентификатор.

  • 0
    Библиотека google.oauth2 поддерживает функции делегирования по всему домену, только если вы используете ключ P12, если это правда, это ошибка, и вы должны регистрировать ее на форумах по проблемам, о которых я раньше не слышал
  • 0
    Если я попробую это, я получу «Эта библиотека реализует поддержку только PKCS # 12 через библиотеку pyOpenSSL. Либо установите pyOpenSSL, либо, пожалуйста, преобразуйте файл .p12 в формат .pem», даже если у меня установлен pyOpenSSL ...?
3

Клиент неавторизован для получения токенов доступа, используя этот метод.

В консоли Google Develoepr есть несколько разных типов клиентов.

  • Браузер - используется для веб-приложений.
  • Родной - используется для установленных приложений
  • Учетная запись службы - используется для связи между сервером и сервером
  • мобильный

Код, используемый для аутентификации с этими разными типами, по понятным причинам отличается.

Код, который вы используете, представляется правильным кодом для python с учетной записью службы. Хотя from_json_keyfile_name принимает файл p12, а не файл.json.

Там для клиента должен быть в corect. Вернитесь в консоль разработчика Google, создайте клиент учетной записи службы и загрузите правильный.json файл.

Учетная запись службы 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)

Я рекомендую использовать файл.json по файлу p12, я подозреваю, что Google не будет использовать их в какой-то момент в будущем.

  • 0
    Есть проблема. Если я импортирую from oauth2client.service_account import ServiceAccountCredentials него есть метод credentials.create_delegated, который позволяет мне загружать файлы определенного пользователя, но этот объект не поддерживает учетные данные учетной записи службы в JSON, но когда я использую ваш импорт, я могу загрузить учетную запись службы учетные данные в JSON, но нет метода create_delegated. :)
  • 0
    @ deb0rian так в чем же решение?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню