# 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": "", "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": "", "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 `. ### Headers ``` Authorization: Bearer ``` ### 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": "", "exp": } ``` | 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": "" } ``` 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)