Autenticação
A API possui três canais de autenticação (um por request).
| Canal | Cliente | Credencial | Persistência |
|---|---|---|---|
| Sessão operador | Painel e Admin | Cookie kunk_oss_session |
system_users |
| Sessão associado | Cadastramento | Cookie associate_session |
users |
| API Key | Scripts, webhooks, apps externos | Authorization: Bearer <token> |
users_api / api_tokens |
O app admin ( / :4256) reusa a sessão operador; o front e as rotas admin exigem role Administrador. Ver ../frontend/admin/.
1. Sessão operador (painel)
Seção intitulada “1. Sessão operador (painel)”| Atributo | Valor |
|---|---|
| Nome | kunk_oss_session |
| HttpOnly | true |
| Secure | true (produção) |
| SameSite | Lax |
| Path | / |
| Max-Age | alinhado a session_expires (ex.: 168h / 1 semana, sliding) |
O frontend não deve ler o token via JavaScript.
Endpoints
Seção intitulada “Endpoints”POST /auth/login
Seção intitulada “POST /auth/login”Autentica operador interno (system_users).
Body
{ "email": "user@example.com", "password": "••••••••"}Resposta 200
{ "data": { "user": { "id": 1, "user_code": "…", "name": "…", "last_name": "…", "email": "…", "permissions": ["Administrador"], "internal_code": "…" } }, "meta": null, "errors": null}Seta cookie kunk_oss_session. Senha com bcrypt. Nunca retornar password / session_token no body.
Erros: 400 VALIDATION_ERROR · 401 INVALID_CREDENTIALS · 403 USER_INACTIVE · 429 RATE_LIMITED (5 falhas / 5 min por IP+e-mail; teto 30 falhas / 5 min por IP. Acertos não contam.)
POST /auth/logout
Seção intitulada “POST /auth/logout”Invalida a sessão atual do operador.
GET /auth/me
Seção intitulada “GET /auth/me”Retorna o operador autenticado. 401 se cookie inválido/expirado.
Validação (middleware operador)
Seção intitulada “Validação (middleware operador)”- Ler cookie
kunk_oss_session - Buscar
system_userscom token ativo - Verificar expiração / inatividade
req.auth = { type: "session", subject: "operator" }
1b. Sessão associado (cadastramento)
Seção intitulada “1b. Sessão associado (cadastramento)”Sessão do app de cadastramento. Detalhe:
../frontend/cadastramento/api.
| Atributo | Valor |
|---|---|
| Nome | associate_session |
| HttpOnly / Secure / SameSite / Path | iguais ao operador |
| Domain | raiz da associação (cross-subdomain se necessário) |
Separado de kunk_oss_session (operador) para não colidir painel × cadastro. O nome session_token fica reservado a outras superfícies.
Endpoints
Seção intitulada “Endpoints”| Método | Path | Função |
|---|---|---|
| POST | /auth/associate/register-email |
{ email, password } → cria fase 1 + cookie (senha min. 8) |
| POST | /auth/associate/login |
{ email, password } |
| POST | /auth/associate/logout |
|
| GET | /auth/associate/me |
responsável sem senha |
| POST | /auth/associate/forgot-password |
{ email } → 200 genérico; envia link se SMTP ok |
| POST | /auth/associate/reset-password |
{ token, password } — invalida sessões do associado |
- Credenciais:
users.email_account+users.account_password(bcrypt). - Sessão:
users.session_*. - Reset: token opaco, TTL 1h, colunas
password_reset_token/password_reset_expires(armazenar hash do token). Rate limit por IP+e-mail. - Register: 409
ACCOUNT_EXISTS/ACCOUNT_IN_PROGRESS— ver api do cadastramento.
Operador — reset de senha
Seção intitulada “Operador — reset de senha”| Método | Path | Função |
|---|---|---|
| POST | /auth/forgot-password |
{ email, app: "kunk"|"admin"|"doc-sign" } → 200 genérico |
| POST | /auth/reset-password |
{ token, password } (política: 8+, maiúscula, especial) |
Link do e-mail aponta para {URL_DO_APP}/nova-senha?token=…. Colunas system_users.password_reset_*. SQL: alter-system-users-password-reset.sql.
Convite de operador
Seção intitulada “Convite de operador”| Método | Path | Função |
|---|---|---|
| GET | /auth/system-invite/preview |
Preview público do token |
| POST | /auth/system-invite/accept |
Define senha e ativa usuário pending |
| POST | /system-users |
Admin cria operador sem senha (pending) + envia convite |
| POST | /system-users/:id/resend-invite |
Reenvia convite |
Validação (middleware associado)
Seção intitulada “Validação (middleware associado)”- Ler cookie
associate_session - Buscar
userscom token ativo (login não é registrostatus=patient) req.auth = { type: "session", subject: "associate" }- Escopo: próprio user + pacientes vinculados
2. API Key (Bearer)
Seção intitulada “2. API Key (Bearer)”Authorization: Bearer kunk_live_xxxxxxxxModelo de dados
Seção intitulada “Modelo de dados”Tabela users_api (tokens de API):
| Campo | Tipo | Nota |
|---|---|---|
id |
serial | PK |
name |
text | rótulo |
token_hash |
text | hash (nunca plaintext) |
token_prefix |
text | identificação |
scopes |
jsonb | escopos |
expires_at / revoked_at / last_used_at |
timestamptz |
Na criação, retornar o token uma vez em plaintext.
POST /auth/tokensGET /auth/tokensDELETE /auth/tokens/:idValidação Bearer
Seção intitulada “Validação Bearer”- Extrair Bearer → verificar hash / revoked / expires
req.auth = { type: "api_key", scopes }
Escopos: ver authorization.
3. Regras de segurança
Seção intitulada “3. Regras de segurança”- Senhas e API tokens sempre hasheados
- Cookies HttpOnly; sem token no
localStorage - Rate limit em login / register-email / forgot-password
- CORS restrito às origens do painel/cadastro
- HTTPS em produção
- Não logar senhas/cookies/Bearer
- Um request: Bearer ou cookie operador ou cookie associado
4. Compatibilidade
Seção intitulada “4. Compatibilidade”| Atual | Novo |
|---|---|
POST /api/auth/login + cookie |
POST /api/v1/auth/login (operador) |
Cookie em Kunk_Users |
system_users + session_token |
| Login associaanteriores | /auth/associate/* + associate_session |
API_TOKEN + plaintext |
Bearer com hash + escopos |
