Autenticação
Sessão interna para app.kroz.co e chamadas programáticas à API: tokens HMAC, cookie HttpOnly e Bearer.
Visão geral
A kroz usa autenticação interna em duas camadas:
- Edge middleware: bloqueia
/api/*(exceto rotas públicas) e páginas HTML - Handler: cada endpoint revalida o token via
requireInternalAuth
Rotas públicas (sem sessão):
| Rota | Motivo |
|---|---|
GET/POST /api/auth |
Login e verificação |
POST /api/baas-webhook |
Webhook inbound do BaaS (token próprio) |
Login no app (browser)
UI
- Acesse app.kroz.co
- Tela kroz // acesso restrito
- Campo Código de acesso
- Botão Entrar
Fluxo técnico
auth-gate.js → GET /api/auth (cookie?)
→ se 401: overlay até POST login
→ se 200: token em sessionStorage + cookie HttpOnly
SessionStorage (cliente):
| Key | Conteúdo |
|---|---|
kroz.internal.token |
Token JWT-like |
kroz.internal.expiresAt |
Unix expiry |
Obter sessão via API
Verificar sessão
curl -s https://app.kroz.co/api/auth \
-H "Cookie: kroz_internal_session=<token>"
200 (sessão válida):
{
"authorized": true,
"token": "eyJ...",
"expiresAt": 1750000000,
"expiresIn": 3600
}
401 (expirada):
{
"authorized": false,
"message": "Sessão interna inválida ou expirada."
}
Login (JSON)
curl -s -X POST https://app.kroz.co/api/auth \
-H "Content-Type: application/json" \
-d '{"code": "SEU_ACCESS_CODE", "redirect": "/rateio"}'
200 (sucesso):
{
"authorized": true,
"token": "eyJ...",
"expiresAt": 1750000000,
"expiresIn": 3600
}
Header Set-Cookie: kroz_internal_session=...; Path=/; Max-Age=3600; HttpOnly; SameSite=Lax; Secure
| Erro | Status | Mensagem |
|---|---|---|
| Código errado | 401 | Código de acesso inválido. |
| Rate limit | 429 | Muitas tentativas de login. Aguarde um minuto e tente novamente. |
| Servidor sem config | 503 | ACCESS_CODE não configurado no servidor. |
| JSON inválido | 400 | JSON inválido. |
Rate limit: 10 POST/min por IP.
Login (form redirect)
POST /api/auth com Content-Type: application/x-www-form-urlencoded:
code=SEU_ACCESS_CODE&redirect=/pagadoria
Sucesso → 303 redirect + cookie. Falha → 303 com ?auth=failed.
Logout
GET /api/auth?logout=1
303 → / + cookie Max-Age=0.
Formato do token
{base64url(payload)}.{hmac_sha256_signature}
Payload:
{
"scope": "internal",
"iat": 1750000000,
"exp": 1750003600,
"nonce": "<24-char hex>"
}
| Parâmetro | Valor |
|---|---|
| TTL | 3600 s (1 hora) |
| Secret | INTERNAL_AUTH_SECRET (preferido) ou fallback ACCESS_CODE |
| Cookie | kroz_internal_session |
⚠️ Produção: use
INTERNAL_AUTH_SECRETdiferente deACCESS_CODE.
Chamadas programáticas
Header Bearer
curl -s https://app.kroz.co/api/platform-contracts?reference=PS-0421&tenantSlug=incorp-piloto \
-H "Authorization: Bearer <token>"
O SDK interno (platform-api.js) injeta automaticamente:
KrozPlatform.getAuthToken() // sessionStorage
Headers em POSTs mutáveis
| Header | Obrigatório | Uso |
|---|---|---|
Authorization: Bearer <token> |
✅ | Sessão |
Content-Type: application/json |
✅ | Body JSON |
Origin |
✅* | CORS em rotas protegidas |
X-Idempotency-Key |
✅** | Escritas reais no BaaS |
* Deve estar em INTERNAL_ALLOWED_ORIGINS
** Max 120 chars: cobranças, subcontas, transferências, conciliação
401 genérico (middleware)
{
"ok": false,
"authorized": false,
"message": "Sessão interna inválida ou expirada."
}
Variáveis de ambiente
| Variável | Obrigatória | Descrição |
|---|---|---|
ACCESS_CODE |
✅ prod | Código de login |
INTERNAL_AUTH_SECRET |
Recomendada | Secret HMAC (≠ ACCESS_CODE) |
INTERNAL_ALLOWED_ORIGINS |
Recomendada | Origens CORS: ex.: https://app.kroz.co |
Preview local (dev)
| Bypass | Condição |
|---|---|
?preview=ui |
Localhost: UI sem auth |
localStorage.kroz.uiPreview=1 |
Persistente em dev |
Falha /api/auth em localhost |
Auto preview UI |
Não usar em produção.
Permissões e tenants
Estado atual: escopo internal: todos os operadores autenticados compartilham a mesma sessão piloto.
Tenant é passado por query/body (tenantSlug): não há RBAC por papel na API ainda.
| Roadmap | Descrição |
|---|---|
| API keys por incorporadora | Token scoped a tenant_id |
| Papéis | DF, operador, readonly |
| SSO | Integração corporativa |
Boas práticas
- ✅ Rotacionar
ACCESS_CODEeINTERNAL_AUTH_SECRETseparadamente - ✅ Usar Bearer + cookie: não expor token em URLs
- ✅ Tratar 401 com re-login (token expira em 1h)
- ❌ Não commitar
ACCESS_CODEno repo - ❌ Não desabilitar middleware em produção
Relacionado
- Referência de API: todos os endpoints
- Webhooks: auth separada (
x-baas-webhook-token) - Adaptadores BaaS: confirmações tipadas para execução real