Как использовать Google API без проверки client_secret.json в системе контроля версий?

Я работаю над проектом, в котором в соответствии с https://12factor.net/config мы не такие вещи, как учетные данные в нашем коде, а скорее в переменных среды.

Я изучаю использование API Google Sheets для сопоставления некоторых данных из нашей базы данных и помещения их в лист Google. Вот частичный пример скрипта с сайта https://developers.google.com/sheets/api/quickstart/python:

from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file as oauth_file, client, tools

# Setup the Sheets API
SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'
store = oauth_file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
    creds = tools.run_flow(flow, store)
service = build('sheets', 'v4', http=creds.authorize(Http()))

Во-первых, из документации мне непонятно, какие 'token.json' и 'credentials.json' должны быть в этом примере. Из консоли API на вкладке «Учетные данные» я загрузил client_secret_<long suffix>.json, который выглядит так:

{"installed":{"client_id":"[our_client_id]","project_id":"nps-survey-1532981793379","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"[our_client_secret]","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

Должен ли этот файл JSON быть 'token.json' в этом примере или 'credentials.json'? Кроме того, есть ли способ создать действительный экземпляр creds, указав секрет клиента и идентификатор клиента напрямую, а не используя этот файл JSON?


person Kurt Peek    schedule 30.07.2018    source источник
comment
Вы можете вызвать конструктор Credentials напрямую с соответствующими значениями. Обратите внимание, что роль token.json заключается в поддержании токена доступа и соответствующей информации между выполнениями скрипта. Это не требуется.   -  person tehhowch    schedule 31.07.2018
comment
Не думайте, что вы можете избавиться от файла учетных данных.json, так как именно в нем хранятся ваши учетные данные. Кроме того, это упоминается в разделе Использование OAuth 2.0 для приложений веб-сервера Не храните файл client_secret.json в общедоступном месте. Кроме того, если вы делитесь исходным кодом со своим приложением, например, на GitHub, храните файл client_secret.json за пределами исходного дерева, чтобы избежать непреднамеренного раскрытия ваших учетных данных клиента. поэтому подразумевается, что вам всегда понадобится этот файл.   -  person noogui    schedule 31.07.2018
comment
К сожалению, платформа, на которой мы развертываем, Aptible, «построена» из Dockerfile и переменных среды; невозможно добавить файл в контейнер, не проверив его в системе контроля версий. (Развертывание запускается при нажатии git). В настоящее время я изучаю несколько хакерский способ, которым я удаляю ключи из файла JSON и «перестраиваю» его из переменных среды.   -  person Kurt Peek    schedule 31.07.2018
comment
В некоторых программных средах CI вы можете настроить инициализацию контейнера из веб-интерфейса, в котором вы безопасно предоставляете переменные среды. Возможно, такой подход есть в Aptible? Я полагаю, что их служба поддержки клиентов должна быть в состоянии помочь вам   -  person tehhowch    schedule 31.07.2018


Ответы (1)


В итоге я прошел настройку OAuth 2.0 для веб-приложения вместо установленного приложения и использовал google_auth_oauthlib. Объект Flow имеет метод класса from_client_config(), который можно использовать следующим образом (см. https://developers.google.com/identity/protocols/OAuth2WebServer):

from django.conf import settings
from django.shortcuts import redirect
import google.oauth2.credentials
import google_auth_oauthlib.flow


# Client configuration for an OAuth 2.0 web server application
# (cf. https://developers.google.com/identity/protocols/OAuth2WebServer)
CLIENT_CONFIG = {'web': {
    'client_id': settings.GOOGLE_CLIENT_ID,
    'project_id': settings.GOOGLE_PROJECT_ID,
    'auth_uri': 'https://accounts.google.com/o/oauth2/auth',
    'token_uri': 'https://www.googleapis.com/oauth2/v3/token',
    'auth_provider_x509_cert_url': 'https://www.googleapis.com/oauth2/v1/certs',
    'client_secret': settings.GOOGLE_CLIENT_SECRET,
    'redirect_uris': settings.GOOGLE_REDIRECT_URIS,
    'javascript_origins': settings.GOOGLE_JAVASCRIPT_ORIGINS}}

# This scope will allow the application to manage your calendars
SCOPES = ['https://www.googleapis.com/auth/calendar']



def get_authorization_url():
    # Use the information in the client_secret.json to identify
    # the application requesting authorization.
    flow = google_auth_oauthlib.flow.Flow.from_client_config(
        client_config=CLIENT_CONFIG,
        scopes=SCOPES)

    # Indicate where the API server will redirect the user after the user completes
    # the authorization flow. The redirect URI is required.
    flow.redirect_uri = 'http://localhost:8000'

    # Generate URL for request to Google's OAuth 2.0 server.
    # Use kwargs to set optional request parameters.
    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    return authorization_url, state

Атрибуты settings, в свою очередь, генерируются вызовом os.getenv() для каждого соответствующего атрибута. Таким образом, конфигурацию можно получить из переменных среды, а не из локального файла.

person Kurt Peek    schedule 07.08.2018
comment
Я загрузил файл конфигурации из консоли API, который предоставляет данные, которые у вас есть здесь, в CLIENT_CONFIG. Однако, когда я пытаюсь запустить flow.fetch_token(), я получаю ValueError: Please supply either code or authorization_response parameters. Есть идеи, что он пытается мне сказать? - person sixty4bit; 24.08.2020