Autenticação GCP: RefreshError
Para enviar o código de envio de e-mail de teste em nosso back-end do GCP, estou enviando um e-mail para uma caixa de entrada do GMail e tentando verificar sua chegada. O mecanismo atual de autenticação para a API do GMail é bastante padrão, colado na documentação da API do GMail e incorporado em uma função:
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
aponta para um arquivo de credenciais baixado para o serviço. A ausência dotoken.json
O arquivo aciona sua recriação após uma interação de autenticação por uma janela do navegador, assim como a expiração do token.
Este é um teste de integração que deve ser executado sem cabeça (ou seja, sem nenhuma interação). Quando a autenticação é necessária, o teste atualmente gera uma exceção quando o fluxo de autenticação começa a acessarsys.argv
, o que significa que ele vê os argumentos parapytest
!
Eu tenho tentado descobrir como autenticar de forma confiável usando um mecanismo que não requer interação do usuário (como uma chave de API). Nada na documentação ou no Stackoverflow parece responder a essa pergunta.
Um esforço mais recente usa o arquivo de chave de uma conta de serviço com a delegação do GMail para evitar os fluxos interativos do 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
Ao tentar usar este serviço com
response = service.users().messages().list(userId='me',
q=f'subject:{subject}').execute()
Eu recebo:
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}')
Tenho a sensação de que há algo fundamental que não estou entendendo.