MundiX - API de Autenticação¶
Task: MX-2026-000123
Implementado: 2026-02-03
Endpoints¶
POST /auth/register¶
Registrar novo usuário.
Request:
{
"username": "johndoe",
"email": "john@example.com",
"password": "SecurePass123!",
"is_admin": false
}
Response (201):
{
"id": 1,
"username": "johndoe",
"email": "john@example.com",
"is_active": true,
"is_admin": false,
"created_at": "2026-02-03T17:30:00Z"
}
POST /auth/login¶
Login e receber tokens.
Request (OAuth2 form):
Response (200):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "a1b2c3d4e5f6...",
"token_type": "bearer",
"expires_in": 900
}
access_token: JWT válido por 15 minutosrefresh_token: Opaque token válido por 7 dias
POST /auth/refresh¶
Renovar access token usando refresh token.
Request:
Response (200):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "z9y8x7w6v5u4...",
"token_type": "bearer",
"expires_in": 900
}
Importante: - Refresh token antigo é revogado automaticamente - Usar refresh token revogado retorna 401
POST /auth/logout¶
Logout (revoga refresh token).
Request:
Response (204 No Content)
GET /auth/me¶
Obter informações do usuário autenticado.
Headers:
Response (200):
{
"id": 1,
"username": "johndoe",
"email": "john@example.com",
"is_active": true,
"is_admin": false,
"created_at": "2026-02-03T17:30:00Z"
}
Protegendo Endpoints¶
Use a dependency get_current_user para proteger endpoints:
from fastapi import Depends
from api.dependencies import get_current_user
from common.models import User
@app.get("/protected")
async def protected_endpoint(current_user: User = Depends(get_current_user)):
return {"message": f"Hello {current_user.username}!"}
Verificar Admin¶
from api.dependencies import get_current_admin_user
@app.post("/admin/action")
async def admin_action(current_user: User = Depends(get_current_admin_user)):
# Only admins can access
return {"message": "Admin action completed"}
Fluxo de Autenticação¶
┌─────────────┐
│ Client │
└──────┬──────┘
│
│ 1. POST /auth/login
│ {username, password}
▼
┌────────────────────────────┐
│ API: /auth/login │
│ - Valida credenciais │
│ - Gera access_token (JWT) │
│ - Gera refresh_token │
│ - Salva refresh no DB │
└──────┬─────────────────────┘
│
│ 2. Response
│ {access_token, refresh_token}
▼
┌─────────────┐
│ Client │
│ (armazena) │
└──────┬──────┘
│
│ 3. GET /agents
│ Authorization: Bearer <access_token>
▼
┌────────────────────────────┐
│ Middleware: verify_token │
│ - Valida JWT │
│ - Extrai user_id │
│ - Injeta current_user │
└──────┬─────────────────────┘
│
│ 4. Response {agents: [...]}
▼
┌─────────────┐
│ Client │
└──────┬──────┘
│
│ (após 15 min, access_token expira)
│
│ 5. POST /auth/refresh
│ {refresh_token}
▼
┌────────────────────────────┐
│ API: /auth/refresh │
│ - Valida refresh_token │
│ - Revoga token antigo │
│ - Gera novos tokens │
└──────┬─────────────────────┘
│
│ 6. Response
│ {access_token (novo), refresh_token (novo)}
▼
┌─────────────┐
│ Client │
└─────────────┘
Exemplo de Uso (cURL)¶
1. Registrar usuário¶
curl -X POST http://localhost:8001/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"email": "test@example.com",
"password": "TestPass123!"
}'
2. Login¶
curl -X POST http://localhost:8001/auth/login \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=testuser&password=TestPass123!"
Resposta:
3. Acessar endpoint protegido¶
export TOKEN="eyJ..." # Access token do login
curl http://localhost:8001/agents \
-H "Authorization: Bearer $TOKEN"
4. Refresh token¶
export REFRESH="abc..." # Refresh token do login
curl -X POST http://localhost:8001/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "'$REFRESH'"}'
5. Logout¶
curl -X POST http://localhost:8001/auth/logout \
-H "Content-Type: application/json" \
-d '{"refresh_token": "'$REFRESH'"}'
Exemplo Python Client¶
import requests
BASE_URL = "http://localhost:8001"
# 1. Login
response = requests.post(
f"{BASE_URL}/auth/login",
data={"username": "testuser", "password": "TestPass123!"}
)
tokens = response.json()
access_token = tokens["access_token"]
refresh_token = tokens["refresh_token"]
# 2. Acessar API protegida
headers = {"Authorization": f"Bearer {access_token}"}
agents = requests.get(f"{BASE_URL}/agents", headers=headers).json()
print(agents)
# 3. Refresh quando access token expirar
response = requests.post(
f"{BASE_URL}/auth/refresh",
json={"refresh_token": refresh_token}
)
new_tokens = response.json()
access_token = new_tokens["access_token"]
refresh_token = new_tokens["refresh_token"]
# 4. Logout
requests.post(
f"{BASE_URL}/auth/logout",
json={"refresh_token": refresh_token}
)
Testes¶
Ver tests/test_auth.py (MX-2026-000123-C).
Security Review¶
Ver docs/SECURITY_REVIEW_MX-2026-000123.md (MX-2026-000123-D).
Arquivos Implementados¶
common/auth.py- Crypto utils (JWT, bcrypt, SHA256)common/models.py- Models User + RefreshTokenapi/auth.py- Endpoints /auth/*api/dependencies.py- Middlewares get_current_userapi/main.py- Registrar auth routerdocs/auth.md- Este documentodocs/ADR-001-auth.md- Architecture Decision Record
Status: ✅ Implementação completa
Próxima etapa: Testes (MX-2026-000123-C)