09 de ago. de 2025·8 min de leitura

Consolidar dois sistemas de autenticação sem prejudicar usuários existentes

Aprenda a consolidar dois sistemas de autenticação com segurança: escolha o certo, migre usuários, remova cookies e tabelas extras e faça o rollout sem logouts surpresa.

Consolidar dois sistemas de autenticação sem prejudicar usuários existentes

O problema: dois logins em um app e usuários presos no meio

Dois sistemas de login separados criam um estado intermediário estranho para os usuários. Eles fazem login em uma tela e são mandados para um prompt de login diferente em outro lugar. Pode parecer tudo ok em testes locais, enquanto usuários reais relatam logouts aleatórios, falta de acesso ou loops infinitos de redirecionamento.

As pistas geralmente são pouco glamourosas, mas óbvias quando você olha: duas telas de login diferentes, dois conjuntos de cookies com nomes semelhantes e checagens de autenticação misturadas que às vezes procuram um cookie de sessão e outras vezes esperam um JWT. Na aba de rede você pode ver um endpoint definindo um cookie como session enquanto outro define algo como auth_token.

Isso aparece muito em prototipagem rápida e em código gerado por IA. Uma ferramenta adiciona um pacote de autenticação pronto, depois um prompt posterior adiciona um login customizado 'só por enquanto', ou um template de framework é mesclado com uma API existente. Nada substitui totalmente o caminho antigo, então os dois continuam ativos.

O que costuma quebrar primeiro é a canalização em torno do login, não o formulário de login:

  • Redefinições de senha atualizam uma tabela de usuários, mas o app lê a outra.
  • Verificação de e-mail é aplicada em um fluxo e ignorada no outro.
  • Papéis e permissões checam claims diferentes ou colunas diferentes no DB.
  • Sessões de 'lembrar-me' nunca combinam com o middleware que protege páginas.

A parte arriscada é que remover o pedaço errado pode trancar usuários reais sem aviso. Você apaga um cookie 'duplicado' e pensa que limpou, mas aquele cookie pode ser a única coisa que mantém sessões antigas válidas. Ou você derruba uma tabela de sessões 'não usada' e descobre que jobs em background (ou um cliente mobile) dependiam dela para renovar tokens.

Trate a consolidação como uma migração de usuários, não como uma limpeza de código. O objetivo é ter uma fonte única de verdade, com uma sobreposição controlada para que contas e sessões existentes continuem funcionando.

Faça um inventário claro do que existe agora

Antes de mudar qualquer coisa, liste cada peça móvel de autenticação. A maioria das falhas de consolidação acontece porque alguma checagem invisível (middleware, um guard de API, uma função de edge) ainda espera o cookie ou formato de sessão antigo.

Nomeie as duas abordagens em termos simples, mesmo que o código esteja bagunçado. Por exemplo: 'NextAuth cookie session' vs 'JWT customizado em localStorage'. Depois escreva o que cada sistema controla: UI de login, acesso à API, registros no banco, páginas administrativas, jobs em background e callbacks de terceiros.

Para cada sistema, responda estas perguntas:

  • O que prova que o usuário está logado (nome do cookie, header, formato do token)?
  • Onde isso é aplicado (middleware, rotas do servidor, funções de edge, handlers de API)?
  • Quais dados ele lê e escreve (tabela de usuários, tabela de sessões, refresh tokens, papéis)?
  • Quais páginas ou endpoints dependem disso (admin, billing, uploads, webhooks)?
  • Quais segredos e regras de validação estão envolvidos (JWT secret, chaves OAuth, hashing de senha)?

Enquanto você faz o inventário, marque riscos de produção que já vê: segredos comprometidos no repo, checagens de token que decodificam mas nunca verificam, SQL montado a partir de strings e rotas que pulam verificações de permissão.

Como escolher o sistema de autenticação a manter

O objetivo não é escolher o 'melhor' sistema em teoria. É escolher o que é mais seguro de rodar, mais fácil de manter e menos provável de te surpreender às 2 da manhã.

Comece com suas prioridades. Para a maioria das equipes, segurança e manutenção vencem conveniência. Se ninguém na equipe entende um dos sistemas, isso é um risco real mesmo que ele pareça polido.

Em seguida, confirme qual sistema os usuários reais realmente usam. Não confie apenas na UI. Verifique logs de sign-in, escritas recentes nas tabelas de sessão e tickets de suporte que mencionem 'não consigo entrar' ou 'deslogado de novo'. Frequentemente um sistema lida com a maior parte do tráfego enquanto o outro é usado só em fluxos de borda.

Finalmente, confirme as funcionalidades necessárias. O sistema que você mantiver precisa suportar o que seu app precisa hoje.

Checklist rápido de seleção

Mantenha o sistema que cobre seus requisitos essenciais com menos código customizado:

  • Métodos de login necessários (email/senha, magic links, logins sociais, SSO)
  • Papéis, times e permissões (se seu app os tiver)
  • Defaults seguros (manuseio de senha, rotação de token, proteção CSRF onde necessária)
  • Fronteiras claras no código (um lugar para criar sessões, um lugar para checar autenticação)
  • Depuração fácil e mensagens de erro claras

Se estiver indeciso, um desempate prático é fronteiras e modelo de dados. A opção que espalha checagens de autenticação por rotas aleatórias, escreve em múltiplas tabelas 'só por precaução' e cria cookies extras continuará causando bugs.

Exemplo: se a autenticação do framework lida de forma confiável com cookies de sessão, enquanto um login customizado também define seu próprio cookie e linha de sessão, mantenha a autenticação do framework e migre o fluxo customizado para ela.

Entenda usuários, sessões e modelo de dados antes de tocar no código

Antes de consolidar qualquer coisa, esteja claro sobre o que 'um usuário' significa no seu app agora. Dois sistemas de autenticação costumam criar duas identidades para a mesma pessoa, e o app muda silenciosamente entre elas. Pular esta etapa leva a logouts aleatórios, dados faltando e confusão de conta.

Trace como um registro de usuário é criado e correlacionado. Logins estão ligados ao e-mail, a um UUID interno, a um provider ID (Google/GitHub) ou a uma mistura? Observe casos de borda: mudanças de e-mail, diferenças de caixa (User@ vs user@), e usuários que se registraram duas vezes com métodos diferentes.

Verifique onde as senhas de fato vivem. Um sistema pode armazenar hashes de senha em uma tabela de usuários, enquanto o outro nunca guardou senhas (por exemplo, só login social). Não assuma que você pode 'mover senhas' entre sistemas. Na maioria dos casos você não pode e não deve.

Depois mapeie sessões de ponta a ponta: o que é definido no navegador, o que é armazenado no servidor e o que o app checa em cada requisição. É comum encontrar múltiplos tipos de sessão ativos ao mesmo tempo.

Escreva um resumo de uma página:

  • Identificadores de usuário: colunas e regras usadas para casar contas
  • Métodos de autenticação habilitados: senha, magic link, provedores OAuth
  • Mecanismo de sessão: cookies, sessões com backing em DB, JWTs, refresh tokens
  • Onde o estado de sessão é armazenado: tabelas, cache, local storage
  • Tabelas duplicadas: duas tabelas de usuários, duas tabelas de sessões, tabelas de perfil 'sombra'

Também procure duplicatas 'inofensivas' que não são inofensivas, como uma tabela de perfis que é a fonte real de verdade para permissões ou status de assinatura.

Projete a migração para que contas existentes continuem funcionando

O estado alvo é uma fonte única de verdade para identidade (quem é o usuário) e autorização (o que ele pode fazer). Todo o resto vira uma camada de compatibilidade que você pode remover depois.

Decida qual será o registro real do usuário. Esse registro deve ter o ID canônico, e-mail e campos de papel/permissão. Então faça com que todo caminho de login acabe nesse mesmo ID, mesmo se a requisição começar no sistema legado.

Se os sistemas usam IDs diferentes de usuário, crie um mapeamento. A abordagem mais segura é uma ponte explícita: armazene o ID antigo no registro do usuário mantido ou adicione uma pequena tabela de mapeamento. Evite tentar reescrever IDs no lugar se eles são referenciados em muitas tabelas.

Senhas são onde as migrações mais quebram usuários. Se você pode reutilizar hashes de senha com segurança, copie o hash mais os metadados necessários (algoritmo, salt, fatores de custo) e mantenha o verificador antigo por um tempo. Só force resets quando realmente não for possível validar hashes antigos, ou quando um problema de segurança exigir.

Defina políticas para casos comuns antes de começar:

  • Emails duplicados: escolha um vencedor por último login ou por email verificado, e coloque o outro em quarentena.
  • Perfis ausentes: crie perfis mínimos no primeiro login bem-sucedido.
  • Usuários de teste e dados seed: marque e exclua-os das contagens de migração.
  • Sessões órfãs: expire-as com segurança em vez de tentar 'consertá-las'.

Exemplo: se você tem autenticação do framework e um login customizado, mantenha a tabela de usuários do framework e importe usuários customizados com um campo old_id. Usuários continuam fazendo login, e você aposenta o caminho customizado gradualmente.

Plano de rollout passo a passo que evita logouts em massa

Free auth consolidation audit
Envie seu repositório e mapearemos cada cookie, token e guard de autenticação antes de você mudar qualquer coisa.

O caminho mais seguro é uma sobreposição curta onde o app pode ler ambos os sistemas, depois uma parada controlada de escrita no antigo. Você quer que sessões existentes continuem funcionando enquanto novos logins migram para a nova fonte de verdade.

Comece pelas bordas: middleware que lê cookies, guards de auth da API e código de lookup de sessão. É aí que logouts surpresa normalmente aparecem.

Um rollout prático:

  • Fase 1 (compat): aceite ambos os formatos de token/cookie e mapeie-os para o mesmo ID interno de usuário.
  • Fase 2 (migração silenciosa): quando chegar uma requisição com uma sessão antiga, reemita uma nova sessão e defina o cookie novo junto com o antigo.
  • Fase 3 (troca de escrita): crie novas sessões apenas no sistema mantido. Pare de escrever na tabela de sessão antiga e pare de definir o cookie antigo no login.
  • Fase 4 (limpeza): depois de uma data de corte clara e monitoramento, remova caminhos de código, cookies e tabelas antigas.

Entre fases, observe sinais reais antes de avançar: taxa de sucesso de login, picos de 401/403, erros 'user not found' e tickets de suporte sobre deslogamento. Se algo saltar, reverta o switch de escrita (Fase 3) antes de remover a compatibilidade de leitura (Fase 1).

Exemplo: se o app define tanto um cookie do framework quanto um JWT customizado, continue lendo ambos por uma ou duas semanas, mas só emita o cookie do framework após a troca.

Cookies e tokens: remover extras sem quebrar sessões

Cookies e tokens são onde a consolidação quebra primeiro. Um sistema pode usar um cookie de sessão assinado, enquanto o outro usa um JWT mais um refresh token. Usuários ficam logados em um lugar e deslogados em outro.

Comece listando cada cookie e token relacionado à autenticação que seu app define e onde ele é definido. Inclua middleware do servidor, código cliente e helpers do framework. Essa é a única maneira segura de remover cookies de autenticação duplicados.

Inventarie o essencial:

  • Nome do cookie e propósito (session, refresh, CSRF, 'remember me')
  • Quem o define (rota do servidor, código cliente, plugin do framework)
  • Escopo (domain, path, SameSite, Secure, HttpOnly)
  • Como é validado (chave de assinatura, chave de criptografia, segredo do token)
  • Onde é lido (API, páginas SSR, middleware de edge)

Colisões de cookie são um problema escondido comum. Dois sistemas podem reaproveitar o mesmo nome de cookie com chaves de assinatura diferentes, ou definir cookies em escopos distintos (app.example.com vs example.com). Isso pode causar logouts aleatórios, redirects infinitos ou autenticação como sessão errada.

Se encontrar uma colisão, planeje um rename limpo em vez de tentar fazer os dois funcionarem para sempre. Introduza um novo nome de cookie para o sistema que você manterá, aceite ambos brevemente e depois remova o antigo.

Logout precisa de cuidado extra durante a sobreposição. Usuários vão clicar em 'log out' e esperar que tudo seja limpo. Durante a migração, faça o logout apagar tanto os cookies antigos quanto os novos (e revogar tokens server-side se você usa refresh tokens). Caso contrário, você pode ter um login fantasma onde o cookie antigo os autentica de novo imediatamente.

Exemplo: uma ferramenta de IA adicionou sessões NextAuth e um cookie JWT customizado chamado auth. Se ambos existirem, seu servidor pode aceitar NextAuth enquanto o cliente continua enviando o JWT. Escolha um, renomeie o cookie mantido se necessário, e adicione uma ponte temporária que transforme um cookie antigo válido na nova sessão.

Limpeza de banco de dados: sessões, usuários e tabelas de autenticação remanescentes

Harden auth while you merge
Sinalizaremos segredos expostos, verificações de token fracas e rotas de risco durante a consolidação.

Erros no banco são como a consolidação vira logouts em massa ou brechas de segurança. Trate a limpeza como uma migração, não como apertar o botão de deletar.

Mapeie cada tabela relacionada à autenticação e decida o que fazer com ela:

  • Manter: usada ativamente pelo sistema escolhido (users, sessions, refresh tokens)
  • Mesclar: contém dados reais de usuário que você deve trazer adiante (profiles, emails, hashes de senha)
  • Arquivar: útil para suporte e rollback (sessões legadas, contas legadas)
  • Dropar: realmente sem uso após validação

Antes de tocar a produção, escreva migrações reversíveis. Em vez de deletar linhas de sessão legadas, copie-as para uma tabela de arquivo com timestamp e depois mude o app para parar de ler a tabela legada.

Torne referências enfadonhas (e corretas)

Dados de autenticação não são isolados. Papéis, membership em orgs, permissões e logs de auditoria frequentemente apontam para um ID de usuário específico. Se a nova autenticação usar IDs diferentes, você precisa de um plano de tradução claro.

Uma abordagem simples é adicionar um campo de mapeamento estável (como legacy_user_id) na tabela de usuário mantida, migrar usuários e depois atualizar referências em pequenos lotes. Faça o mesmo para sessões: se havia sessions e user_sessions, escolha uma fonte de verdade e adapte o código a ela.

Uma sequência de rollout que reduz surpresas:

  • Backfill de novas tabelas e colunas de mapeamento sem mudar comportamento.
  • Atualize o app para ler da nova fonte enquanto escreve brevemente em duplicidade se necessário.
  • Verifique papéis/orgs/permissões para contas reais (incluindo admins).
  • Troque escritas para as tabelas mantidas apenas.
  • Arquive e depois drope tabelas legadas após um período de resfriamento.

Também confirme que nada mais toca as tabelas antigas: jobs em background, dashboards administrativos, scripts de analytics, ferramentas de suporte e cron jobs. Esse é um lugar comum para um segundo caminho de autenticação se esconder.

Erros comuns que deslogam usuários ou abrem buracos de segurança

A maneira mais rápida de criar uma onda de tickets é remover peças antigas antes que o caminho novo cubra todos os fluxos reais de usuário. O app pode parecer bem no seu navegador, mas usuários de produção têm cookies antigos, sessões pela metade e links salvos.

Erros que causam logouts em massa ou novas brechas:

  • Desabilitar middleware antigo cedo demais, fazendo com que sessões existentes parem de ser reconhecidas.
  • Mudar rotas de reset ou verificação no meio da migração, quebrando e-mails já enviados ou verificando a conta errada.
  • Deixar checagens de token permissivas (aceitar tokens sem verificação adequada, pular checks de issuer/audience ou não expirar sessões).
  • Esquecer outros clientes (apps mobile, ferramentas admin, jobs em background, webhooks recebidos) que ainda enviam o cookie ou token antigo.
  • Não testar comportamento de cookie entre subdomínios e ambientes (localhost vs staging vs produção), fazendo cookies serem descartados por causa de domain, SameSite ou flags Secure.

Um exemplo concreto: você remove o cookie de sessão antigo porque o sistema novo usa JWTs, mas uma ferramenta administrativa embutida em admin.yoursite.com só conhece o cookie de sessão. Ela quebra, e alguém 'conserta' desabilitando checagens de autenticação nessa rota. É assim que migrações criam brechas.

Duas ações de segurança reduzem risco:

  • Mantenha ambos os validadores ativos brevemente e registre qual deles foi usado por requisição.
  • Congele caminhos de URL para links de reset/verify até que e-mails antigos expirem e redirecionamentos sejam confirmados.

Checagens rápidas para rodar antes e depois do deploy

A limpeza mais segura é aquela que você consegue desfazer rapidamente. Mudanças de código são metade do risco. A outra metade é o que acontece em navegadores reais com cookies antigos e sessões pela metade.

Antes do release, confirme:

  • O inventário está completo: cada nome de cookie, header token, store de sessão e tabela relacionada está documentada.
  • Um sistema é a fonte de verdade para identidade e papéis, e todas as rotas leem dele.
  • Nomes e escopos de cookie estão confirmados (domain, path, SameSite, Secure), com plano para ignorar ou substituir cookies antigos.
  • Existe um plano de rollback que está a um deploy de distância (por exemplo, uma feature flag que reabilita a checagem de sessão antiga).
  • Sua matriz de testes foi escrita e executada para signup, login, logout, reset de senha e checagens de papel/permissão.

Não conte com uma conta feliz no caminho feliz. Teste pelo menos um usuário criado em cada sistema antigo, mais um usuário 'bagunçado' que tenha ambos os cookies setados. É aí que os bugs se escondem.

Após o release, monitore comportamento mais do que código:

  • Monitore falhas de login por motivo (token inválido, sessão ausente, mismatch CSRF, papel negado), não apenas a contagem total.
  • Acompanhe a taxa de criação de sessões e compare com o tráfego normal.
  • Confirme que a tabela de sessão antiga e tabelas legadas não recebem novas escritas após o cutover.
  • Verifique fluxos em uma janela anônima e em um navegador “sujo” que ainda tenha cookies antigos.
  • Quando estável, remova segredos e chaves antigas, delete sessões antigas e só então drope tabelas remanescentes.

Um exemplo realista: mesclando uma autenticação de framework com um login customizado

Find your second auth path
Identificaremos a verdadeira fonte da verdade e os checadores legados escondidos que causam logouts aleatórios.

Uma situação comum gerada por IA é: a UI usa NextAuth (cookies, callbacks, uma tabela de sessions), depois alguém adiciona um login JWT customizado 'só para a API'. Agora você tem duas fontes de verdade sobre quem é o usuário.

Os sintomas confundem. Um usuário pode entrar e navegar na UI, mas chamadas de API retornam 401 porque esperam um Bearer token. Ou a API funciona no Postman com um JWT, mas a UI continua mandando para a tela de login porque a sessão via cookie está ausente. Pior, o mesmo e-mail pode acabar com dois IDs de usuário diferentes dependendo de qual caminho criou a conta.

A correção mais segura é escolher um vencedor e migrar sem forçar todo mundo a se registrar novamente. Se você consolidar no NextAuth, mantenha o caminho JWT customizado vivo temporariamente como camada de compatibilidade.

Uma migração prática:

  • Escolha o ID único real do usuário (normalmente a tabela de usuários do NextAuth) e mapeie usuários só-JWT para ele.
  • Aceite ambos temporariamente: permita que requisições API se autentiquem via cookie de sessão ou via JWT antigo, mas resolva ambos para o mesmo ID de usuário no código do servidor.
  • Quando os usuários fizerem o próximo login (ou refresh), emita apenas o método de sessão mantido e pare de mintar novos JWTs.
  • Após uma janela curta, remova a verificação de JWT, delete o cookie extra e aposente tabelas de sessão/token não usadas.

Uma limpeza segura termina com um cookie, um store de sessão e um ID de usuário usados em todo lugar.

Próximos passos: quando pedir ajuda

Se você não consegue explicar em uma frase como uma requisição vira um usuário autenticado no seu app, pare. Essas mudanças parecem pequenas, mas podem trancar pessoas ou enfraquecer a segurança silenciosamente.

Sinais de que você deve parar e pedir uma segunda opinião

Você provavelmente passou de 'limpeza simples' para 'projeto de migração' se:

  • Você não consegue mapear cada usuário para uma identidade única (duas tabelas de usuários, e-mails divergentes, IDs duplicados).
  • Você não sabe como as senhas são hasheadas (ou vê mais de um método de hashing).
  • Checagens de papel estão misturadas (algumas rotas usam middleware, outras checam um cookie customizado, outras consultam o DB).
  • Sessões e cookies se sobrepõem (usuários parecem logados, mas chamadas de API falham ou a identidade muda).

O que preparar para uma revisão

Você obterá respostas melhores e mais rápidas se reunir um pequeno pacote de fatos primeiro:

  • Acesso ao repo (ou uma exportação limpa) mais a configuração atual de deploy
  • Uma lista de variáveis de ambiente relacionadas à autenticação (nomes de cookie, segredos JWT, client IDs OAuth, URLs de callback)
  • Um dump do esquema do DB e contagens de linhas para users, sessions e outras tabelas de autenticação
  • Logs recentes relacionados a login, refresh de token e erros de não autorizado
  • Uma nota curta sobre o que os usuários relatam (logouts forçados, contas erradas, acesso admin quebrado)

Se essa bagunça foi criada por ferramentas de IA e você precisa de um plano de limpeza focado em produção, FixMyMess (fixmymess.ai) ajuda equipes a diagnosticar autenticação entrelaçada, remover cookies duplicados e caminhos de sessão, e endurecer o código antes que algo quebre em produção.

Perguntas Frequentes

How do I confirm I actually have two auth systems?

Comece listando cada ponto de entrada de login, cookie, token, tabela de sessão e guard de autenticação. Em muitos apps quebrados, o problema real não é o formulário de login, mas o middleware escondido e as checagens de API que ainda esperam o formato legado.

Which auth system should I keep?

Mantenha o que já atende a maior parte do tráfego real e que tem padrões seguros e claros. Se um sistema for um 'cola' customizada espalhada por rotas aleatórias, enquanto o outro tem um fluxo de sessão bem definido, o centralizado costuma ser a escolha mais segura.

Why can’t I just delete the extra login and cookie?

Porque remover uma autenticação 'duplicada' frequentemente quebra sessões existentes e tranca usuários sem aviso. Trate isso como uma migração de usuários: permita uma breve sobreposição em que você lê ambos os formatos, depois mude as escritas e só então limpe.

How do I avoid creating two identities for the same person?

Escolha um registro de usuário canônico e faça com que todo caminho de autenticação resolva para esse mesmo ID interno. Se os dois sistemas usam IDs diferentes, adicione um mapeamento explícito (por exemplo, um campo old_id ou uma tabela de mapeamento) em vez de reescrever IDs por toda parte de uma vez.

Can I migrate passwords from the old system to the new one?

Normalmente, não, e você não deve tentar migrar senhas a menos que entenda totalmente o formato de hash antigo e seus metadados (algoritmo, salt, custo). Um padrão mais seguro é continuar verificando hashes antigos durante um período de transição ou obrigar reset apenas quando realmente não for possível validar as credenciais antigas.

What’s the safest way to remove extra cookies and tokens?

Faça um inventário explícito de cookies e tokens: nomes, escopos, quem os cria e quem os lê. Durante o rollout, aceite ambos brevemente, depois passe a emitir apenas o cookie mantido, e faça o logout apagar tanto o cookie antigo quanto o novo para evitar logins "fantasma".

What rollout plan prevents mass logouts?

Use fases: compatibilidade de leitura primeiro, depois reemissão silenciosa de novas sessões quando aparecerem as antigas, então pare de escrever no sistema antigo e só depois exclua tabelas e código antigos. Avance para a próxima fase apenas depois de ver taxas estáveis de sucesso de login e sem picos de 401/403.

What if both systems use similar cookie names or scopes?

Renomeie o cookie mantido para um nome novo e único e aceite o antigo apenas temporariamente. Colisões acontecem porque dois sistemas reaproveitam o mesmo nome de cookie com chaves diferentes ou definem escopos (domain/path) distintos, o que pode causar loops de redirecionamento e logouts aleatórios.

How do I clean up duplicate users/sessions tables safely?

Não delete de primeira; arquive e prove que nada grava mais nas tabelas legadas. Uma abordagem prática é preencher campos de mapeamento, alternar leituras, escrever em duplicidade brevemente se necessário, então alternar escritas, arquivar sessões/contas legadas e só então eliminar.

When should I bring in help (and what should I prepare)?

Se você não consegue explicar em uma frase como uma requisição vira um usuário autenticado entre UI, API e jobs, você já entrou no território de migração. Se isso foi criado por código gerado por IA e você precisa de um plano de consolidação seguro rápido, FixMyMess (fixmymess.ai) pode rodar uma auditoria de código gratuita e ajudar a unificar a autenticação sem quebrar usuários existentes.