Como autenticar numa API REST com OAuth 2.0 em Python
As APIs de dados mais robustas não estão abertas ao público: exigem autenticação. Em cenários servidor a servidor, o padrão mais comum é o OAuth 2.0 com o fluxo client credentials, e dominá-lo é essencial para construir pipelines de dados fiáveis. Este guia mostra, passo a passo, como obter um access token e chamar um endpoint protegido em Python.
Pré-requisitos
- Python 3.8 ou superior instalado.
- A biblioteca
requests(instala-se compip install requests). - As credenciais da API:
client_ideclient_secret, fornecidos pelo portal do fornecedor. - O URL do token endpoint (onde se pedem os tokens) e o URL do recurso protegido que queres consumir.
Passo 1: Entender o fluxo client credentials
O OAuth 2.0 define vários fluxos. O de client credentials é o indicado quando é a tua aplicação — e não um utilizador — a aceder aos dados, como acontece num script de ETL ou num serviço agendado. A ideia é simples: a aplicação apresenta o seu client_id e o seu client_secret a um token endpoint, recebe em troca um access token temporário e usa esse token para autenticar cada pedido à API. Não há ecrãs de login nem intervenção humana, o que o torna ideal para automação.
Passo 2: Obter o access token
O primeiro pedido é um POST ao token endpoint, indicando grant_type=client_credentials. A resposta é um JSON com o token e o seu tempo de validade em segundos (expires_in). Repara que as credenciais vão no corpo do pedido, sobre HTTPS, e nunca no URL.
import requests
TOKEN_URL = "https://auth.example.com/oauth/token"
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
def get_token():
response = requests.post(TOKEN_URL, data={
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"scope": "data.read",
}, timeout=10)
response.raise_for_status()
return response.json()["access_token"]
token = get_token()
print("Access token obtained")
O método raise_for_status() garante que um erro de credenciais (HTTP 401) interrompe logo o script, em vez de continuar com um token inválido.
Passo 3: Chamar o endpoint protegido
Com o token em mãos, cada pedido à API leva o cabeçalho Authorization: Bearer <token>. É assim que o servidor sabe que estás autorizado.
API_URL = "https://api.example.com/v1/customers"
def get_data(token):
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(API_URL, headers=headers, timeout=10)
response.raise_for_status()
return response.json()
records = get_data(token)
print(f"Received {len(records)} records")
Passo 4: Reutilizar o token e tratar a expiração
Pedir um token novo a cada chamada é lento e, muitas vezes, está sujeito a limites. O melhor é guardar o token e o seu instante de expiração, renovando-o apenas quando falta pouco tempo. Uma classe simples resolve o problema:
import time
class APIClient:
def __init__(self):
self._token = None
self._expires_at = 0
def valid_token(self):
# Refresh 60 seconds before expiry, to be safe
if not self._token or time.time() > self._expires_at - 60:
response = requests.post(TOKEN_URL, data={
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
}, timeout=10)
response.raise_for_status()
payload = response.json()
self._token = payload["access_token"]
self._expires_at = time.time() + payload["expires_in"]
return self._token
client = APIClient()
headers = {"Authorization": f"Bearer {client.valid_token()}"}
Assim, o mesmo token é reutilizado enquanto for válido e renovado automaticamente quando necessário.
Verificar o resultado
Para confirmar que tudo funciona, corre o script e verifica dois sinais: o pedido do token devolve HTTP 200 e a chamada à API devolve dados em vez de um erro 401. Se receberes um 401, revê o client_id, o client_secret e o scope. Um erro 403 significa que o token é válido mas não tem permissões para aquele recurso — nesse caso, o problema está nas scopes atribuídas à aplicação.
Conclusão
Com estes passos tens uma base sólida para autenticar qualquer API de dados que use OAuth 2.0 client credentials, desde a obtenção do token até à sua renovação automática. O próximo passo natural é combinar isto com paginação e escrita numa base de dados, transformando estas chamadas num pipeline completo. Que API vais integrar primeiro?