Pular para conteúdo

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:

  1. O cliente envia um Bearer token no header Authorization.
  2. Se ENABLE_MOCK_ACCESS_TOKEN=true e o token segue o formato mock.matricula.<número>, a matrícula é extraída direto do token.
  3. Caso contrário, o token é validado via JWKS obtido do Keycloak (src/infrastructure.identity-provider/jwks/, biblioteca jwks-rsa v4).
  4. A API busca o Usuario no banco pela matrícula.
  5. Se existe, um RequestActor com id, nome, matricula, email e isSuperUser é injetado nos controllers.
  6. 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.