Skip to content

Instantly share code, notes, and snippets.

@mbmaciel
Created July 13, 2026 14:19
Show Gist options
  • Select an option

  • Save mbmaciel/44715cbfdc09ec9d9fcc8c7e1afb85c8 to your computer and use it in GitHub Desktop.

Select an option

Save mbmaciel/44715cbfdc09ec9d9fcc8c7e1afb85c8 to your computer and use it in GitHub Desktop.
Multi-dominios por Tenant
Multi-dominios por Tenant
Objetivo
Permitir que a aplicacao autenticada resolva a entidade pelo dominio acessado antes do login, exibindo nome, logotipo e cores do tenant na tela inicial.
Exemplos:
https://sitraslo.plenocrm.com.br deve abrir o login com logotipo, nome e tema do sindicato SITRASLO.
https://app.plenocrm.com.br deve continuar como dominio padrao do PlenoCRM, usado pelo usuario MASTER.
Se o usuario acessar um subdominio inexistente, como https://qualquercoisa.plenocrm.com.br, o sistema deve se comportar como https://app.plenocrm.com.br.
Se o usuario fizer login pelo dominio errado, o sistema deve levar o usuario para o subdominio correto do tenant dele.
Regras do Produto
app.plenocrm.com.br e dominio padrao da aplicacao autenticada.
app.plenocrm.com.br nao representa tenant cliente; deve manter branding padrao PlenoCRM.
Cada tenant cliente pode possuir um subdominio principal, por exemplo sitraslo.plenocrm.com.br.
Subdominios desconhecidos nao devem gerar erro visual nem tela quebrada; devem cair no comportamento padrao do app.plenocrm.com.br.
O login deve aceitar credenciais em qualquer dominio valido, mas apos autenticar deve redirecionar para o dominio canonico do usuario:
usuario MASTER -> https://app.plenocrm.com.br
usuario com tenant_id -> subdominio principal do tenant, quando configurado
usuario com tenant_id sem subdominio configurado -> https://app.plenocrm.com.br
O backend continua sendo a fonte da verdade para isolamento por tenant_id; o dominio melhora a experiencia e ajuda a selecionar o branding, mas nao substitui RBAC nem validacoes de tenant.
Fase 1 — Modelo de Dados e Cadastro
Objetivo: registrar o dominio canonico de cada tenant e preparar validacoes.
Task Descricao Status
1.1 Criar migration adicionando custom_domain ou primary_subdomain em tenants ✅
1.2 Criar indice unico case-insensitive para subdominio/dominio, ignorando valores nulos ✅
1.3 Reservar subdominios internos: app, api, www, admin, master, plenocrm ✅
1.4 Validar formato do subdominio no backend: letras, numeros e hifen, sem protocolo, barra ou ponto extra quando for subdominio simples ✅
1.5 Expor o campo no cadastro/edicao de tenants no painel MASTER ✅
1.6 Registrar auditoria quando o subdominio do tenant for criado, alterado ou removido ✅
Decisao sugerida
Para o MVP, usar primary_subdomain em vez de dominio completo.
Exemplo:
tenants.primary_subdomain = "sitraslo"
host gerado = "sitraslo.plenocrm.com.br"
Isso reduz risco de configuracao incorreta, evita misturar dominios externos no primeiro ciclo e facilita validacao.
Fase 2 — Resolucao Publica de Tenant
Objetivo: descobrir o tenant pelo host antes do login e devolver dados publicos de branding.
Task Descricao Status
2.1 Criar helper backend para normalizar Host e extrair subdominio de *.plenocrm.com.br ✅
2.2 Criar endpoint publico GET /public/tenant-by-host?host=sitraslo.plenocrm.com.br ✅
2.3 Retornar apenas dados publicos: name, slug, primary_color, secondary_color, logo_url, primary_subdomain ✅
2.4 Para app.plenocrm.com.br, retornar branding padrao PlenoCRM e indicar que nao ha tenant cliente ✅
2.5 Para subdominio desconhecido, retornar o mesmo payload padrao de app.plenocrm.com.br ✅
2.6 Nao revelar se um tenant existe por mensagens de erro detalhadas em dominio invalido ✅
Fase 3 — Login com Branding por Host
Objetivo: aplicar a identidade visual correta antes do usuario autenticar.
Task Descricao Status
3.1 No frontend, detectar window.location.hostname ao carregar a tela de login ✅
3.2 Buscar o branding publico do host antes de renderizar o login final ✅
3.3 Exibir logotipo, nome e cores do tenant quando o host pertencer a um tenant ativo ✅
3.4 Manter logotipo e nome PlenoCRM quando o host for app.plenocrm.com.br ou desconhecido ✅
3.5 Criar estado de carregamento discreto para evitar piscar branding errado no login ✅
3.6 Se o tenant estiver inativo, mostrar login padrao e bloquear autenticacao desse tenant no backend ✅
Fase 4 — Redirecionamento para Dominio Correto
Objetivo: garantir que o usuario sempre termine no dominio canonico dele.
Task Descricao Status
4.1 Incluir no retorno de POST /auth/login o campo canonical_host ou canonical_url ✅
4.2 Para MASTER, retornar app.plenocrm.com.br como destino canonico ✅
4.3 Para usuario de tenant com subdominio, retornar <primary_subdomain>.plenocrm.com.br ✅
4.4 No frontend, apos login, comparar host atual com host canonico ✅
4.5 Se forem diferentes, salvar token de forma compativel com o dominio raiz e redirecionar para o host correto ✅
4.6 Revalidar sessao no destino com GET /auth/me e aplicar o branding do tenant autenticado ✅
Observacao importante sobre sessao
Para redirecionamento entre subdominios funcionar bem, a estrategia de sessao precisa ser definida:
O token continua em localStorage para compatibilidade com o frontend atual.
Para o redirecionamento entre subdominios, foi adicionado um cookie de handoff limitado a hosts *.plenocrm.com.br, com dominio .plenocrm.com.br, Secure e SameSite=Lax.
Evolucao recomendada: migrar a sessao para cookie HTTP-only emitido pelo backend.
Fase 5 — Infraestrutura e Deploy
Objetivo: preparar DNS, proxy e frontend para aceitar qualquer subdominio de tenant.
Task Descricao Status
5.1 Configurar DNS wildcard *.plenocrm.com.br apontando para a aplicacao autenticada ✅
5.2 Manter api.plenocrm.com.br apontando para o backend/API ✅ Infra
5.3 Configurar certificado TLS wildcard para *.plenocrm.com.br ✅ Infra
5.4 Configurar Nginx/proxy para servir o mesmo build React em app.plenocrm.com.br e subdominios de tenant ✅ Infra
5.5 Ajustar frontend/vite.config.ts para permitir hosts locais de teste quando necessario ✅
5.6 Validar CORS no backend para aceitar origens de https://*.plenocrm.com.br sem liberar origens arbitrarias ✅
Fase 6 — Testes e Criterios de Aceite
Task Descricao Status
6.1 Teste backend: resolver tenant existente por host ✅
6.2 Teste backend: host app.plenocrm.com.br retorna branding padrao ✅
6.3 Teste backend: subdominio inexistente retorna branding padrao ✅
6.4 Teste backend: MASTER recebe dominio canonico app.plenocrm.com.br no login ✅
6.5 Teste backend: usuario de tenant recebe dominio canonico do seu tenant ✅
6.6 Teste frontend: login em sitraslo.plenocrm.com.br exibe logo e nome do sindicato ✅
6.7 Teste frontend: login em subdominio desconhecido exibe PlenoCRM ✅
6.8 Teste E2E: usuario autenticado pelo dominio errado e levado ao subdominio correto ✅
A tela de login em sitraslo.plenocrm.com.br mostra identidade visual do SITRASLO antes da autenticacao.
A tela de login em app.plenocrm.com.br mostra identidade visual padrao PlenoCRM.
Um subdominio inexistente nao mostra erro e nao exibe dados de outro tenant.
Usuario MASTER sempre opera em app.plenocrm.com.br.
Usuario de tenant sempre opera no subdominio canonico do tenant, quando configurado.
Nenhuma rota de negocio passa a confiar apenas no dominio para isolamento multi-tenant.
Notas de Seguranca
Nunca derivar tenant_id de negocio apenas do host em rotas autenticadas; usar sempre o JWT e as permissoes do backend.
O host pode ser usado para branding publico e para sugestao de contexto de login.
Validar e normalizar host para evitar ataques com headers manipulados.
Em producao atras de proxy, confiar em X-Forwarded-Host apenas se o proxy for controlado e a aplicacao estiver configurada para isso.
Nao permitir que um tenant escolha subdominio reservado ou ja usado por outro tenant.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment