Pular para conteúdo

0018 — Adota xadm-seguranca: infra transversal de auth vem da lib

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-09 · Decidido em: 2026-08-11

Contexto. O Integrador foi a fonte da extração da xadm-seguranca — o SessionAuthenticationFetcher local (sessão JWT das views, login Firebase) é o código de onde a lib nasceu. Enquanto a lib não existia, o app carregava essa infra transversal em br.com.xadm.comum; 0016/0017 declararam explicitamente que adotar a xadm-seguranca estava fora de escopo (o fetcher local bastava para o gate da tela). Com a lib publicada e endurecida, essa infra vira recópia de código da casa — constituição §5 Baseline (app Micronaut consome as libs transversais, não as espelha). É a Fase 2 da iniciativa libs+contrato (a Fase 1 foi a xadm-comum-web, 0017). Este DR revoga a nota "fora de escopo" de 0016/0017.

Decisão.

  • Adotar xadm-seguranca:0.3.0; dropar a infra transversal local. Seis classes de auth — AuthException, AuthSettings, MicronautProfiles, FirebaseIdTokenValidator, SessionTokenService, SessionAuthenticationFetcher — eram equivalentes às da lib (só pacote/javadoc diferiam) e saíram de br.com.xadm.comum; imports repointados para br.com.xadm.comum.seguranca.*. Os testes que exercitavam API package-private da lib (SessionTokenServiceTest, FirebaseIdTokenValidatorTest, MicronautProfilesTest) foram removidos — a cobertura dessa mecânica agora é responsabilidade do repo xadm-commons.
  • Política de auth fica local (por desenho). A lib traz a infra; a policy é per-app e permanece em br.com.xadm.comum: ViewSecurityRule (tri-estado enabled/bypass/fail-closed), ViewRejectionHandler (302/401/403/503), ApiBearerSecurityRule, e o AuthSupport (whitelist de paths + atributos de request). Mesmo nome de conceito ≠ mesma decisão — a whitelist e o tri-estado são escolhas deste app.
  • StaticBearerTokenValidator fica local via @Replaces. A lib 0.3.0 já endureceu a comparação (constant-time MessageDigest.isEqual + guard de vazio — o feedback §6 do ciclo anterior landou na lib), mas lê ${app.api-token}. Este app lê ${api.bearer.token} (env INTEGRADOR_API_TOKEN, já injetada por tenant no Coolify) — adotar a da lib exigiria renomear o secret de deploy. O @Replaces(br.com.xadm.comum.seguranca.StaticBearerTokenValidator.class) neutraliza o bean da lib sem duplicar validação divergente. Paridade de segurança preservada.
  • SUPERADO em 2026-08-21 (d2c7d60): o bean local foi removido e o app adotou o StaticBearerTokenValidator da lib, renomeando a property de api.bearer.token para app.api-token — a env de deploy continua INTEGRADOR_API_TOKEN, que era o custo que esta decisão queria evitar; ele não existia, porque o que precisava mudar era o nome da property, não o do secret. O @Replaces deixou de existir junto. Manter cópia local de validador só para conservar um nome de property contrariava o próprio Baseline que este DR adotou. Com isso o app passou a herdar as guardas de boot da lib: placeholder ${...} não resolvido (0.5.1) e, desde a 0.7.2, app.api-token declarado e vazio (BearerTokenGuard) — fora de dev/test, os dois recusam o boot. Estado atual em dev/seguranca.md.
  • auth.issuer virou config. A lib generalizou o ISSUER antes hardcoded ("integrador") para ${AUTH_ISSUER:integrador} e exige não-vazio no boot (o SessionTokenService da lib falha o contexto senão). O default preserva o valor histórico — deploy existente não muda de comportamento.

Consequências. ./gradlew check sobe o contexto com a xadm-seguranca no classpath e a suíte de auth existente (SecurityRulesTest, AuthSupportTest, LoginControllerTest, GoogleLoginFlowIT, ViewSessionAuthIntegrationTest, LoginPageRenderingIT, NavbarRenderingIT) segue verde — prova de paridade. O feedback de timing-attack do StaticBearer está resolvido na lib 0.3.0. Correção de segurança na casa passa a chegar ao app por bump de versão, não por edição local.

Fora de escopo: a xadm-seguranca em si (repo xadm-commons); adotar CSRF da lib (o SessionAuthenticationFetcher da lib popula o atributo auth.csrf, mas a verificação segue onde está — sem mudança de comportamento de CSRF neste ciclo).

Revisto: o 0019 (seguranca 0.4.0) adotou o CSRF de sessão via CsrfTokens e deduplicou o AuthSupport local (constantes/isHttps vêm da lib; a whitelist virou ViewWhitelist).