3.6 KiB
API Contract: Auth Endpoints
Prefixo: /api/v1/auth
Blueprint: auth_bp em backend/app/routes/auth.py
Content-Type: application/json
Autenticação: Bearer token via header Authorization (onde indicado)
POST /api/v1/auth/register
Cria uma nova conta de cliente. Token de acesso emitido imediatamente na resposta.
Request Body
{
"name": "João Silva",
"email": "joao@exemplo.com",
"password": "minhasenha123"
}
| Campo | Tipo | Obrigatório | Regras |
|---|---|---|---|
name |
string | ✅ | 1–150 caracteres |
email |
string (RFC 5321) | ✅ | Email válido; normalizado para lowercase antes de persistir |
password |
string | ✅ | Mínimo 8 caracteres |
Respostas
201 Created
{
"access_token": "<jwt_string>",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "João Silva",
"email": "joao@exemplo.com",
"role": "client",
"created_at": "2026-04-13T15:00:00"
}
}
409 Conflict — e-mail já cadastrado
{ "error": "E-mail já cadastrado." }
422 Unprocessable Entity — falha de validação Pydantic
{
"error": "Dados inválidos.",
"details": [
{ "loc": ["body", "password"], "msg": "String should have at least 8 characters", "type": "string_too_short" }
]
}
POST /api/v1/auth/login
Autentica um cliente existente e emite token de acesso.
Request Body
{
"email": "joao@exemplo.com",
"password": "minhasenha123"
}
| Campo | Tipo | Obrigatório |
|---|---|---|
email |
string (email válido) | ✅ |
password |
string | ✅ |
Respostas
200 OK
{
"access_token": "<jwt_string>",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "João Silva",
"email": "joao@exemplo.com",
"role": "client",
"created_at": "2026-04-13T15:00:00"
}
}
401 Unauthorized — e-mail não encontrado ou senha incorreta (mesma resposta para não revelar qual campo falhou — FR-007, SC-006)
{ "error": "Credenciais inválidas." }
422 Unprocessable Entity — falha de validação Pydantic
{ "error": "Dados inválidos.", "details": [...] }
GET /api/v1/auth/me
Retorna dados do usuário autenticado. Requer Authorization: Bearer <token>.
Headers
Authorization: Bearer <jwt_string>
Respostas
200 OK
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "João Silva",
"email": "joao@exemplo.com",
"role": "client",
"created_at": "2026-04-13T15:00:00"
}
401 Unauthorized — sem token, token inválido ou token expirado
{ "error": "Token de acesso inválido ou expirado." }
JWT Payload
{
"sub": "<uuid-string do ClientUser>",
"exp": <unix timestamp — now() + 7 dias>
}
| Campo | Valor |
|---|---|
| Algorithm | HS256 |
| Secret | JWT_SECRET_KEY (variável de ambiente) |
| TTL | 7 dias (604800 s) |
Claim sub |
UUID do ClientUser como string |
Envelope de Erro Padrão
Todas as respostas de erro seguem o envelope:
{ "error": "<mensagem legível>" }
Erros de validação 422 incluem details com a lista de erros Pydantic.
Respostas de erro nunca incluem informações que permitam distinguir e-mail vs. senha incorretos (SC-006).
Notas de Segurança
- Nenhuma resposta inclui
password_hash 401em credenciais inválidas NÃO DEVE indicar qual campo está incorretoJWT_SECRET_KEYNUNCA deve aparecer em logs ou respostas da API- CORS configurado explicitamente em
create_app()(sem wildcard em produção)