175 lines
3.6 KiB
Markdown
175 lines
3.6 KiB
Markdown
# 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
|
||
|
||
```json
|
||
{
|
||
"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**
|
||
```json
|
||
{
|
||
"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
|
||
```json
|
||
{ "error": "E-mail já cadastrado." }
|
||
```
|
||
|
||
**422 Unprocessable Entity** — falha de validação Pydantic
|
||
```json
|
||
{
|
||
"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
|
||
|
||
```json
|
||
{
|
||
"email": "joao@exemplo.com",
|
||
"password": "minhasenha123"
|
||
}
|
||
```
|
||
|
||
| Campo | Tipo | Obrigatório |
|
||
|-------|------|-------------|
|
||
| `email` | string (email válido) | ✅ |
|
||
| `password` | string | ✅ |
|
||
|
||
### Respostas
|
||
|
||
**200 OK**
|
||
```json
|
||
{
|
||
"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)
|
||
```json
|
||
{ "error": "Credenciais inválidas." }
|
||
```
|
||
|
||
**422 Unprocessable Entity** — falha de validação Pydantic
|
||
```json
|
||
{ "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**
|
||
```json
|
||
{
|
||
"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
|
||
```json
|
||
{ "error": "Token de acesso inválido ou expirado." }
|
||
```
|
||
|
||
---
|
||
|
||
## JWT Payload
|
||
|
||
```json
|
||
{
|
||
"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:
|
||
|
||
```json
|
||
{ "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`
|
||
- `401` em credenciais inválidas NÃO DEVE indicar qual campo está incorreto
|
||
- `JWT_SECRET_KEY` NUNCA deve aparecer em logs ou respostas da API
|
||
- CORS configurado explicitamente em `create_app()` (sem wildcard em produção)
|