Pular para conteúdo

0023 — Adotar a lib xadm-seguranca

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

Contexto

O motor de auth das views nasceu caseiro (decisão 0018) e era cópia byte-idêntica da mesma stack em ≥3 apps X-Adm (onpetro, thoms, vantroba): validador do Firebase ID token, sessão JWT HS256, CSRF determinístico, Bearer estático, config auth.*. Três cópias do validador do IdP Firebase compartilhado significam três lugares para corrigir uma falha de segurança e três chances de divergirem. O motor foi extraído para a lib canônica br.com.xadm:xadm-seguranca (o vantroba foi a variante-fonte da extração — Javadoc completo).

Decisão

Depender de xadm-seguranca:0.2.0 (Forgejo Packages da org xadm, pública → leitura anônima, mesma fonte da decisão 0015) e deletar as 9 cópias locais do motor (AuthException, AuthSettings, MicronautProfiles, StaticBearerTokenValidator, CsrfTokens, FirebaseIdTokenValidator, SessionTokenService, SessionAuthenticationFetcher, AuthSupport). Migrar os consumidores para br.com.xadm.comum.seguranca. Fica local só o que é do app: a policy de rota (ViewSecurityRule, ViewRejectionHandler), o GlobalViewModel, o LoginController e a whitelist base (ViewWhitelist).

Duas divergências do byte-idêntico, por design:

  • Issuer virou config. O SessionTokenService da lib lê o iss de auth.issuer (antes hardcoded "bi-transporte-xls"). Setado auth.issuer: ${AUTH_ISSUER:bi-transporte-xls} com default fixo = valor idêntico ao hardcode ⇒ zero sessão invalidada e deploy/dev/test sobem sem setar a env. A lib fail-closa se não achar issuer; com o default estático esse fail-closed é rede-morta (só dispara se AUTH_ISSUER for setado vazio).
  • Whitelist é local. Cada app tem a sua (o vantroba não tem /compras/, /webhook/ nem isPublicView); a lib traz o contrato + helpers (AuthSupport: constantes, deveRecusarAnonimo, isHttps) mas não a whitelist. Ela virou ViewWhitelist local; ViewSecurityRule e ViewRejectionHandler consomem ViewWhitelist.isWhitelisted.

Consequências

  • Uma fonte só do validador Firebase/sessão/CSRF; um bump de lib corrige os 3 apps.
  • Paridade provada: o AuthIntegrationTest (login Firebase → xadm_session → rota protegida → CSRF) passa contra o artefato 0.2.0 publicado, sem alterar asserções — o default de issuer supre o claim sem tocar no getProperties().
  • Os testes-espelho do motor (que usavam membros package-private / o test-seam preloadCacheForTesting) foram deletados — a fonte da verdade deles é o xadm-commons da lib. Sobra local a cobertura da parte do app: ViewWhitelistTest, AuthExceptionHandlerTest, LoginControllerTest.
  • A superfície pública da 0.2.0 foi verificada contra o artefato (javap/jar tf), não assumida: preloadCacheForTesting público, AuthSettings.getIssuer(), AuthSupport sem whitelist, e as bean definitions Micronaut presentes (senão a DI não descobriria os beans).

Alternativas consideradas

  • Manter as cópias locais: sem acoplamento à lib, mas 3 validadores do IdP compartilhado divergindo e 3 lugares para corrigir uma falha. Descartado — é o risco que motivou a extração.
  • Unificar a whitelist na lib: cada app tem paths públicos distintos; forçar uma whitelist única vazaria política de um app pro outro. Descartado — a whitelist fica local (ViewWhitelist).
  • Full OIDC já fora descartado na 0018 (muda UX/infra, sem teste). Fora de escopo aqui.