DEV Community

authagonal
authagonal

Posted on • Originally published at authagonal.io

Importar usuários sem redefinição de senha

Todo guia de migração de identidade acaba chegando ao mesmo parágrafo, e ele soa sempre um pouco constrangido: "os usuários precisarão redefinir suas senhas." Isso é tratado como uma lei da natureza. Não é. É uma escolha, quase sempre imposta por uma ferramenta que não quis fazer o mais difícil.

O mais difícil é verificar no lugar os hashes de senha existentes dos seus usuários, para que, depois da virada, eles entrem com exatamente as mesmas credenciais que tinham antes e nunca percebam que algo aconteceu. Se você consegue fazer isso ou não se resume a uma única pergunta: dá para obter os hashes antigos, e o novo sistema consegue verificá-los?

Hashes de senha são mais portáveis do que se imagina

Um hash de senha não é um algoritmo secreto. bcrypt é bcrypt. Um hash bcrypt carrega o próprio fator de custo e o próprio sal dentro da string, então qualquer coisa que implemente bcrypt pode verificar um hash produzido por qualquer outro sistema bcrypt. O mesmo vale para o formato PBKDF2 que o ASP.NET Identity usa: documentado, versionado, autodescritivo. Se você sabe o que tem em mãos, dá para conferir uma senha contra ele sem nunca conhecer a senha.

Portanto, uma migração que preserva os logins não precisa do texto puro (ninguém o tem) nem de re-hashear todo mundo de antemão. Ela precisa obter os hashes armazenados e verificá-los no login, elevando cada um ao próprio formato em silêncio na primeira vez que o usuário entra. Essa última parte é a migração preguiçosa: leve o hash antigo, verifique-o uma vez, substitua-o de forma transparente. Ao longo de algumas semanas de logins normais, sua tabela de usuários se re-hasheia sozinha e os formatos antigos vão sumindo, com zero redefinições e zero chamados de suporte.

A parte do caminho duplo

O detalhe é que fontes diferentes entregam formatos diferentes, e um bom importador verifica os dois:

  • De um Duende / ASP.NET Identity auto-hospedado: os hashes V3 PBKDF2 (e qualquer bcrypt legado) verificam de forma nativa e são re-hasheados no primeiro login. Esse é o caso fácil, porque é o mesmo esquema que o destino já usa. A maioria das equipes se surpreende com como é limpo.
  • Do Auth0: os hashes bcrypt verificam ao pé da letra. O problema não é o formato, é consegui-los.

Quando você realmente não consegue

A Management API do Auth0 nunca devolve hashes de senha. É uma política deliberada, não uma lacuna na ferramenta de ninguém, e você deveria desconfiar de qualquer "exportação do Auth0 em um clique" que afirme incluir senhas sem isso. O caminho suportado é uma exportação em massa assistida pelo suporte: um arquivo NDJSON com o hash bcrypt de cada usuário. Consiga esse arquivo e os hashes são importados ao pé da letra, migração preguiçosa inclusa, e a virada fica invisível.

Se você não pode esperar por isso, a alternativa é a versão honesta do parágrafo constrangido: os usuários definem uma senha nova no primeiro login. Nada foi perdido, porque não havia hash para levar. A diferença é que você escolheu isso de forma consciente, e não porque a ferramenta não dava conta de algo melhor.

Por que isso importa mais do que parece

Uma redefinição forçada é a coisa mais visível e mais alarmante que você pode fazer a uma base de usuários no meio de uma migração. Ela gera carga de suporte, acostuma os usuários a esperar um e-mail em formato de phishing do tipo "clique aqui para redefinir", e é o momento em que uma mudança silenciosa de infraestrutura vira problema de todo mundo. Evitar isso é boa parte do que faz uma migração parecer que nada aconteceu, que é exatamente como uma migração deveria parecer.

Então, antes de aceitar o "todo mundo redefine", faça as duas perguntas. Para a maioria das viradas, a resposta é sim para ambas, e o parágrafo constrangido nunca foi necessário.

Veja o que uma importação carregaria: a prévia é somente leitura e mostra tudo a você antes que qualquer coisa seja gravada.

Top comments (0)