Autenticação e autorização¶
TLDR: autenticação delegada a um servidor Keycloak via OAuth2/OIDC, validada por JWKS, com um mock de token pra desenvolvimento sem depender do Keycloak. Autorização segue "throw on deny" via IPermissionChecker por módulo, hoje implementado como no-op na maioria dos módulos. Os conceitos gerais (JWT, JWKS, OAuth2/OIDC) estão em Autenticação.
| Termo | Vá pra |
|---|---|
| O fluxo real de validação de token | Autenticação |
| Como testar sem Keycloak | Tokens mock em desenvolvimento |
| Como a permissão é verificada | Autorização |
Autenticação¶
sequenceDiagram
participant Cliente
participant API as Management Service
participant KC as Keycloak
participant DB as PostgreSQL
Cliente->>API: requisição com Bearer token
alt token mock (dev)
API->>API: extrai matrícula do token
else token real (produção)
API->>KC: obtém JWKS
KC-->>API: chaves públicas
API->>API: valida assinatura do JWT
end
API->>DB: busca Usuario por matrícula
DB-->>API: dados do usuário
API->>API: monta RequestActor (id, nome, matricula, email, isSuperUser)
Fluxo real, implementado em src/server/nest/auth/request-actor-resolver.adapter.ts:
- O cliente envia um Bearer token no header
Authorization. - Se
ENABLE_MOCK_ACCESS_TOKEN=truee o token segue o formatomock.matricula.<número>, a matrícula é extraída direto do token. - Caso contrário, o token é validado via JWKS obtido do Keycloak (
src/infrastructure.identity-provider/jwks/, bibliotecajwks-rsav4). - A API busca o
Usuariono banco pela matrícula. - Se existe, um
RequestActorcomid,nome,matricula,emaileisSuperUseré injetado nos controllers. - Se não existe,
ForbiddenException.
O JWKS é buscado na URL {OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER}/.well-known/openid-configuration. As credenciais de client (KC_CLIENT_ID, KC_CLIENT_SECRET) autenticam o admin client do Keycloak pra operação administrativa (como criar usuário), não o fluxo de validação de token em si.
Ciclo de vida e cache de validação¶
A autoridade emissora dos tokens é o Keycloak. A duração dos tokens (Access Token Lifespan, SSO Session Idle/Max) é configurada no Realm do Keycloak. O backend aceita dinamicamente a expiração informada pelo Keycloak (expires_in) e mantém um cache LRU de validação (IdentityProviderService) com teto de segurança de 5 minutos, garantindo que revogações de credenciais no Keycloak sejam propagadas para a API mesmo quando os tokens tiverem longa duração.
Tokens mock em desenvolvimento¶
curl -H "Authorization: Bearer mock.matricula.1234" http://localhost:3701/api/campi
Funciona com qualquer matrícula, desde que o Usuario correspondente exista no banco (o seed de migração cria um superuser, ver Banco de dados e transações). ENABLE_MOCK_ACCESS_TOKEN deve ser false em produção.
Autorização¶
flowchart TD
REQ["Requisição autenticada"] --> HANDLER["Command/Query Handler"]
HANDLER --> PC["PermissionChecker do módulo"]
PC -->|CREATE| CAN_C["ensureCanCreate"]
PC -->|UPDATE| CAN_U["ensureCanUpdate"]
PC -->|DELETE| CAN_D["ensureCanDelete"]
CAN_C & CAN_U & CAN_D -->|ok| CONTINUE["Continua execução"]
CAN_C & CAN_U & CAN_D -.->|throw| DENIED["403 Forbidden"]
Cada módulo implementa IPermissionChecker, ver assinatura completa em Padrões de código. O padrão é "throw on deny": sem permissão, ForbiddenError é lançado e a operação é abortada. Operações de leitura (queries) hoje aceitam acesso com ou sem autenticação, accessContext pode ser null. Está no roadmap filtrar resultado de leitura por permissão do usuário, ainda não implementado.