Проверка подлинности GCP: RefreshError

Чтобы проверить код отправки тестового письма в нашем бэкэнде GCP, я отправляю электронное письмо в почтовый ящик GMail и пытаюсь проверить его получение. Текущий механизм аутентификации в API GMail довольно стандартный, вставлен из документации API GMail и встроен в функцию:

def authenticate():
    """Authenticates to the Gmail API using data in credentials.json,
    returning the service instance for use in queries etc."""
    store = file.Storage('token.json')
    creds = store.get()
    if not creds or creds.invalid:
        flow = client.flow_from_clientsecrets(CRED_FILE_PATH, SCOPES)
        creds = tools.run_flow(flow, store)
    service = build('gmail', 'v1', http=creds.authorize(Http()))
    return service

CRED_FILE_PATH указывает на загруженный файл учетных данных для службы. Отсутствие файла token.json запускает его повторное создание после аутентификации через окно браузера, как и истечение срока действия токена.

Это интеграционный тест, который должен выполняться без головы (то есть без какого-либо взаимодействия). Когда требуется повторная аутентификация, тест в настоящее время вызывает исключение, когда поток аутентификации начинает доступ к sys.argv, что означает, что он видит аргументы для pytest!

Я пытался выяснить, как надежно аутентифицироваться с помощью механизма, не требующего взаимодействия с пользователем (например, ключа API). Ничто в документации или на Stackoverflow, похоже, не отвечает на этот вопрос.

Более поздняя попытка использует ключевой файл из учетной записи службы с делегированием GMail, чтобы избежать интерактивных потоков Oauth2.

def authenticate():
    """Authenticates to the Gmail API using data in g_suite_access.json,
    returning the service instance for use in queries etc."""
    main_cred = service_account.Credentials.from_service_account_file(
        CRED_FILE_PATH, scopes=SCOPES)
    # Establish limited credential to minimise any damage.
    credentials = main_cred.with_subject(GMAIL_USER)
    service = build('gmail', 'v1', credentials=credentials)
    return service

При попытке использовать эту услугу с

        response = service.users().messages().list(userId='me',
                                    q=f'subject:{subject}').execute()

Я получил:

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

У меня такое чувство, что я не понимаю чего-то фундаментального.

Почему вы не можете использовать IMAP-доступ к учетной записи Gmail для выполнения этого теста интеграции? Я понимаю, что это не то, с чем вы хотели получить помощь, но кажется, что это намного проще для достижения цели интеграционного теста, как описано.

isp-zax 09.09.2018 04:55

Я действительно подумал об этом, но поскольку мы захотим использовать службы Gmail API для других целей позже, это просто решит проблему в будущем.

holdenweb 09.09.2018 13:48

По иронии судьбы, при дальнейшем изучении решения IMAP у меня возникли проблемы с аутентификацией с помощью IMAP, и дальнейшие исследования привели меня к этот вопрос, где ответ ... использовать аутентификацию OAuth2 !!

holdenweb 09.09.2018 20:47

Ну, это только если вы отключите «доступ для менее безопасных приложений», как там сказано. Так что технически это не препятствие для проверки получения электронной почты - просто нужно изменить этот параметр, чтобы разрешить. Но, поскольку вам в любом случае понадобится GMail API позже, это явно не постоянное решение, а, возможно, временное решение. IMAP полностью работает - я перемещаю содержимое почтовых ящиков Gmail в другое место, используя его.

isp-zax 10.09.2018 00:41

Да, теперь у меня есть резервное решение IMAP, но на данный момент мы договорились, что это может быть тест интеграции, запускаемый вручную. Нам не нужно проверять наши каналы электронной почты каждую минуту, но было бы неплохо знать, что все работает, например, после выпуска нового поставщика. Я все еще надеюсь, что награда затянется, но я не задерживаю дыхание.

holdenweb 10.09.2018 22:50
Может быть, это ?
dsgdfg 11.09.2018 08:28

- Не пугайтесь, но все такие вопросы приветствуются. Теперь я отказался от решения IMAP в пользу flow_from_client_secrets - если мы работаем в интерактивном режиме, тестер может подтвердить правильные учетные данные для аутентификации.

holdenweb 11.09.2018 13:57

Идентификатор gmail, который вы пытаетесь использовать, это идентификатор gsuite или простой идентификатор gmail (@ gmail.com)?

Shubham Sinha 12.09.2018 15:02

Это G-suite (наш собственный домен - одна ошибка заключалась в попытке войти в систему под псевдонимом домена, что не сработало).

holdenweb 13.09.2018 00:01

Я пробовал запустить ваш код, и он работает абсолютно нормально. Пожалуйста, проверьте две вещи: 1. Если вы авторизуете правильные области. 2. Я обычно видел, что эта ошибка возникает, когда при авторизации учетной записи службы отсутствуют области. Правильно ли вы выполнили это - developers.google.com/admin-sdk/directory/v1/guides/delegati‌ на?

Shubham Sinha 14.09.2018 17:19

@holdenweb у тебя была возможность это проверить?

Shubham Sinha 16.09.2018 10:43

Да, очень полезно. Как вы и подозревали, авторизация учетной записи службы не была правильно определена.

holdenweb 16.09.2018 17:17

Большой! Однако пропустил награду :)

Shubham Sinha 17.09.2018 09:52

Я считаю, что необходимо написать ответ, чтобы потребовать награду, и был только один ответ, когда награда истекла. Сожалею!

holdenweb 18.09.2018 05:16

Ага, все в порядке. Спасибо

Shubham Sinha 18.09.2018 12:00
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
15
1 007
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Учетная запись службы должна быть авторизована, иначе она не может получить доступ к электронной почте для домена.

"Client is unauthorized to retrieve access tokens using this method"

Означает, что вы не авторизовали его должным образом; проверьте Делегирование полномочий на уровне домена учетной записи службы

Источник: Клиент не авторизован для получения токенов доступа с помощью этого метода Gmail API C#

Другие вопросы по теме