Autenticação
Quick Reference
Por que a autenticação baseada em token é importante
| Sem gerenciamento adequado de autenticação | Com as boas práticas da A55 |
|---|---|
| Nova requisição de token a cada chamada à API — lento e sujeito a rate limit | Armazene e reutilize o token por até 1 hora |
| Credenciais espalhadas em código, configs e logs | Uma única entrada no gerenciador de segredos, zero exposição |
| Tokens expirados causam falhas 401 silenciosas em produção | Renovação proativa antes da expiração mantém uptime de 100% |
| Depurar problemas de autenticação desperdiça horas de integração | Um fluxo, um endpoint, um formato de token — JWT em toda parte |
Troque client_id + client_secret por um access_token JWT (válido por 1 hora). Envie esse token como Authorization: Bearer <token> em cada chamada à API. Renove antes de expirar.
Fluxo de autenticação
Passo 1 — Solicitar um access token
| Configuração | Valor |
|---|---|
| Endpoint | https://smart-capital.auth.us-east-1.amazoncognito.com/oauth2/token |
| Método | POST |
| Content-Type | application/x-www-form-urlencoded |
| Campo | Valor |
|---|---|
grant_type | client_credentials |
client_id | Seu client ID OAuth 2.0 |
client_secret | Seu client secret OAuth 2.0 |
- cURL
- Python
- JavaScript
curl -s -X POST \
https://smart-capital.auth.us-east-1.amazoncognito.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
import requests
def get_access_token():
url = "https://smart-capital.auth.us-east-1.amazoncognito.com/oauth2/token"
payload = {
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(url, data=payload, headers=headers)
response.raise_for_status()
return response.json()["access_token"]
async function getAccessToken() {
const response = await fetch(
"https://smart-capital.auth.us-east-1.amazoncognito.com/oauth2/token",
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: "YOUR_CLIENT_ID",
client_secret: "YOUR_CLIENT_SECRET",
}),
}
);
const data = await response.json();
return data.access_token;
}
Passo 2 — Entender a resposta do token
{
"access_token": "eyJraWQiOiJLTzZ...",
"expires_in": 3600,
"token_type": "Bearer"
}
| Campo | Tipo | Descrição |
|---|---|---|
access_token | string | JWT usado como token Bearer em cada requisição à API |
expires_in | integer | Tempo de vida do token em segundos (padrão 3600 = 1 hora) |
token_type | string | Sempre Bearer |
Cole seu access_token no jwt.io durante o desenvolvimento para inspecionar claims, escopos e expiração. Nunca faça isso com tokens de produção em sites não confiáveis.
Passo 3 — Chamar a API
Envie Authorization: Bearer <access_token> em cada requisição.
- cURL
- Python
- JavaScript
curl -s -X GET \
https://core-manager.a55.tech/api/v1/wallets \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"
def call_api(access_token: str, method: str, endpoint: str, payload=None):
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
}
url = f"https://core-manager.a55.tech/api/v1/{endpoint}"
response = requests.request(method, url, json=payload, headers=headers)
response.raise_for_status()
return response.json()
async function callApi(accessToken, method, endpoint, payload) {
const response = await fetch(
`https://core-manager.a55.tech/api/v1/${endpoint}`,
{
method,
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: payload ? JSON.stringify(payload) : undefined,
}
);
return response.json();
}
Passo 4 — Armazenar em cache e renovar tokens
Tokens duram 1 hora. Solicite um novo antes de expirar — nunca espere por um 401.
- Python
- JavaScript
import time
import requests
class A55Client:
AUTH_URL = "https://smart-capital.auth.us-east-1.amazoncognito.com/oauth2/token"
API_BASE = "https://core-manager.a55.tech/api/v1"
REFRESH_MARGIN = 300 # renovar 5 min antes da expiração
def __init__(self, client_id: str, client_secret: str):
self._client_id = client_id
self._client_secret = client_secret
self._token = None
self._token_expiry = 0
def _refresh_token(self):
resp = requests.post(self.AUTH_URL, data={
"grant_type": "client_credentials",
"client_id": self._client_id,
"client_secret": self._client_secret,
}, headers={"Content-Type": "application/x-www-form-urlencoded"})
resp.raise_for_status()
data = resp.json()
self._token = data["access_token"]
self._token_expiry = time.time() + data["expires_in"] - self.REFRESH_MARGIN
@property
def token(self) -> str:
if not self._token or time.time() >= self._token_expiry:
self._refresh_token()
return self._token
def request(self, method: str, endpoint: str, **kwargs):
headers = {
"Authorization": f"Bearer {self.token}",
"Content-Type": "application/json",
}
resp = requests.request(method, f"{self.API_BASE}/{endpoint}", headers=headers, **kwargs)
resp.raise_for_status()
return resp.json()
# Exemplo de uso
client = A55Client("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
wallets = client.request("GET", "wallets")
print(wallets)
class A55Client {
#token = null;
#tokenExpiry = 0;
static AUTH_URL = "https://smart-capital.auth.us-east-1.amazoncognito.com/oauth2/token";
static API_BASE = "https://core-manager.a55.tech/api/v1";
static REFRESH_MARGIN = 300_000; // 5 min em ms
constructor(clientId, clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
}
async #refreshToken() {
const resp = await fetch(A55Client.AUTH_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: this.clientId,
client_secret: this.clientSecret,
}),
});
const data = await resp.json();
this.#token = data.access_token;
this.#tokenExpiry = Date.now() + data.expires_in * 1000 - A55Client.REFRESH_MARGIN;
}
async getToken() {
if (!this.#token || Date.now() >= this.#tokenExpiry) {
await this.#refreshToken();
}
return this.#token;
}
async request(method, endpoint, payload) {
const token = await this.getToken();
const resp = await fetch(`${A55Client.API_BASE}/${endpoint}`, {
method,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: payload ? JSON.stringify(payload) : undefined,
});
return resp.json();
}
}
// Exemplo de uso
const client = new A55Client("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");
const wallets = await client.request("GET", "wallets");
console.log(wallets);
Checklist de gerenciamento de tokens
| Prática | Por quê |
|---|---|
| Armazene tokens em cache por até 55 minutos | Evita chamadas desnecessárias ao Cognito e limites de taxa |
Renove 5 minutos antes de expires_in | Previne erros 401 durante chamadas à API |
Armazene o client_secret em um gerenciador de segredos | Variáveis de ambiente vazam em logs; gerenciadores de segredos não |
| Nunca registre tokens ou segredos em logs | Um token vazado concede acesso total à API por 1 hora |
| Use HTTPS em toda parte | Tokens em HTTP texto plano podem ser interceptados |
| Rotacione segredos periodicamente | Limita o raio de impacto se uma credencial for comprometida |
Trate o client_secret como uma senha de banco de dados: armazene apenas no backend, nunca em navegadores, aplicativos mobile, logs de CI ou repositórios públicos. Se comprometido, envie um e-mail para tech.services@a55.tech imediatamente para rotação.
Respostas de erro
| Status HTTP | Significado | O que fazer |
|---|---|---|
401 Unauthorized | Token expirado ou inválido | Renove o token e tente novamente |
400 Bad Request | Requisição de autenticação malformada | Verifique grant_type, client_id, client_secret |
429 Too Many Requests | Limite de taxa atingido no Cognito | Implemente backoff exponencial; armazene seus tokens em cache |
Solicite credenciais
Envie um e-mail para tech.services@a55.tech com o nome da sua empresa, contato técnico e caso de uso esperado para receber client_id e client_secret para sandbox e produção.