Configurar login Google das views¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-06
O que é¶
Habilita o login Google (Firebase) nas views server-rendered (/processamentos/**,
/admin/**), restrito a emails @xadm.com.br. O desenho está na
etapa 06 e na decisão
0003; aqui é o procedimento de
configuração.
- Client: Firebase Authentication (Google sign-in) — popup do Google no navegador.
- Servidor: valida o ID token do Firebase (RS256, contra o JWKS público do
Google via
nimbus-jose-jwt) e emite um cookie de sessão próprio (xadm_session, JWT HS256, TTL 8 h). - Gate: a regra de segurança das views exige o cookie em todo path fora da
whitelist (dentro do
micronaut-security, sem filtro paralelo).
O /api/** (Bearer) não é afetado — a regra das views faz whitelist de /api/**
(decisão 0002).
Quando usar¶
- Subir um ambiente de produção (as views precisam das envs
AUTH_*, senão ficam fail-closed em503). - Apontar o app para um novo domínio público (precisa autorizar o domínio no Firebase).
Pré-requisitos no Firebase (infra, fora do código)¶
Reusa o projeto Firebase existente xadm-6ab81 (compartilhado entre apps X-Adm).
Antes do deploy:
- Authorized domains — Firebase Console → Authentication → Settings →
Authorized domains → adicionar o domínio do deploy (ex.:
excel.onpetro.xadm.biz). Sem isso, osignInWithPopupdo Google falha no navegador. - Provider Google — já habilitado no
xadm-6ab81; nada a fazer. AUTH_SESSION_SECRET— segredo HS256 exclusivo deste deploy, ≥32 chars:openssl rand -hex 32. Nunca reusar de outro deploy/serviço.
Não é necessário o
firebase-admin-sdk.json: a validação do ID token usa só o JWKS público do Google.
Passos¶
Configurar as variáveis no Coolify:
| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
AUTH_FIREBASE_PROJECT_ID |
sim | — | xadm-6ab81 |
AUTH_FIREBASE_API_KEY |
sim | — | Web API key (valor público) |
AUTH_FIREBASE_AUTH_DOMAIN |
sim | — | xadm-6ab81.firebaseapp.com |
AUTH_FIREBASE_APP_ID |
sim | — | Web App ID (valor público) |
AUTH_SESSION_SECRET |
sim | — | segredo HS256 ≥32 chars, exclusivo |
AUTH_SESSION_TTL_SECONDS |
não | 28800 (8 h) |
TTL do cookie |
AUTH_COOKIE_SECURE |
não | true |
Secure (true em prod HTTPS) |
AUTH_XADM_EMAIL_DOMAIN |
não | xadm.com.br |
domínio aceito |
AUTH_ISSUER |
não | bi-comercial-xls |
claim iss do cookie de sessão (lib xadm-seguranca, decisão 0018). Não mudar — o valor é validado na verificação; alterar invalida todas as sessões em voo |
Os 4 AUTH_FIREBASE_* são públicos (vão no HTML da página de login, por design do
Firebase Web SDK). AUTH_SESSION_SECRET é o único segredo — nunca logado, nunca
exposto em HTML.
Fluxo de login / logout¶
- Usuário sem sessão abre uma view → o servidor redireciona para
/login?from=<path>. /loginmostra "Entrar com Google"; o clique abre o popup do Google.- O navegador obtém o ID token do Firebase e faz
POST /login/callback. - O servidor valida CSRF + ID token + domínio
@xadm.com.br, emite o cookiexadm_sessione redireciona de volta para ofromoriginal. - A navbar passa a mostrar o email logado + "Sair" (
POST /logout, expira o cookie).
Verificação¶
- Abrir uma view (
/processamentos) → redireciona para/login→ "Entrar com Google" → após login com conta@xadm.com.br, volta para a view com o email na navbar. - Conta fora do domínio → "Acesso restrito a emails @xadm.com.br" (esperado).
Reversão / comportamento sem as envs¶
Não há "desligar" explícito — o comportamento depende das envs e do ambiente:
| Situação | Comportamento |
|---|---|
Envs AUTH_* completas |
filtro ativo (views exigem login) |
Envs ausentes e ambiente dev/test |
bypass (views públicas, WARN no log) |
| Envs ausentes e produção | fail-closed (503 em todas as views) |
Em produção, sempre configure as 5 variáveis obrigatórias.
Sessão e segurança (caveats)¶
- Sessão stateless (cookie
xadm_session, JWT HS256 auto-contido): não há revogação server-side. O logout só expira o cookie no navegador; um token vazado vale até expirar. O TTL de 8 h (AUTH_SESSION_TTL_SECONDS) limita essa janela. - CSRF: os forms POST de view (
/admin/nuke-replication,/processamentos/{id}/excluir,/processamentos/{id}/reprocessar,/processamentos/{id}/reprocessar-lotee/processamentos/reprocessar-erros) carregam_csrfderivado da sessão; ausente/divergente →403. O enforcement só vale com auth ativo — emdev/test(bypass) o CSRF não é exigido. - Qualquer sessão válida reprocessa. Os três
reprocessar*são ações de escrita liberadas para todo email@xadm.com.brlogado — não há papel de operador vs. leitor. A trava é de estado, não de pessoa: oWHERE … AND status = 'ERRO'doresetarParaPendenteSeErrorecusa (409) tudo que não esteja em ERRO, então o estrago possível é refazer um arquivo que já falhou. Mesmo critério do nuke em/admin.
Troubleshooting¶
| Sintoma | Causa / ação |
|---|---|
Todas as views em 503 |
produção sem as 5 envs obrigatórias — configurar |
| Popup do Google falha (domínio) | domínio do deploy não está em Authorized domains |
Login OK mas volta sempre pro /login |
cookie não persistiu — checar AUTH_COOKIE_SECURE vs HTTPS |
Acesso restrito a emails @xadm.com.br |
conta usada não é do domínio — usar conta @xadm.com.br |
| Bean falha no startup (secret curto) | AUTH_SESSION_SECRET < 32 chars — gerar novo com openssl rand -hex 32 |
| Login intermitente com erro do Google | JWKS do Google indisponível → o servidor responde 503 + Retry-After; tentar de novo |