Políticas de senha pragmáticas (o que realmente melhora a segurança)
Uma política de senha eficaz equilibra três objetivos: reduzir senhas fracas (fáceis de adivinhar), diminuir reutilização (senhas já vazadas) e manter boa usabilidade (para não incentivar comportamentos ruins, como anotar senha ou criar padrões previsíveis). No back-end, isso se traduz em validações no momento de criação/alteração de senha e em mecanismos de recuperação de conta que não abram brechas.
Tamanho mínimo e limites razoáveis
- Comprimento mínimo: prefira 12 caracteres como padrão. Se o seu público tem fricção alta (ex.: mobile), 10 pode ser aceitável, mas compense com checagem de vazamentos e bloqueio de senhas comuns.
- Comprimento máximo: defina um máximo (ex.: 72 ou 128) para evitar abuso de recursos e compatibilidade com algoritmos de hash. Se usar bcrypt, lembre que ele considera apenas os primeiros 72 bytes; então, valide e normalize para não criar falsas expectativas.
- Permitir espaços e Unicode: passphrases com espaços são boas. Se aceitar Unicode, normalize (ex.: NFKC) para evitar confusões visuais e inconsistências.
Bloqueio de senhas comuns e padrões óbvios
Em vez de exigir “1 maiúscula, 1 número, 1 símbolo” (que gera senhas previsíveis), bloqueie diretamente o que é fraco:
- Listas de senhas comuns (ex.: top 10k/100k).
- Senhas contendo o e-mail/username, nome do produto, ou partes do nome do usuário.
- Padrões repetitivos (ex.:
aaaaaa,123123123) e sequências simples (abcdef,qwerty).
Verificação contra vazamentos (credential stuffing prevention “na origem”)
Além de bloquear senhas comuns, verifique se a senha já apareceu em vazamentos conhecidos. A ideia é impedir que o usuário escolha uma senha que já está em bases de credenciais expostas. Isso pode ser feito consultando um serviço de “breached password” (idealmente com um método que não envie a senha em texto puro; use abordagem de prefixo/consulta parcial ou um provedor interno).
Recomendação prática: se a senha estiver vazada, recuse com mensagem genérica do tipo “senha fraca” e, se possível, explique que ela já foi exposta em incidentes.
Regras a evitar (requisitos contraproducentes)
- Troca periódica obrigatória sem evidência de comprometimento: aumenta reutilização e padrões previsíveis (ex.:
Senha@2025viraSenha@2026). - Regras rígidas de composição (maiúscula/número/símbolo obrigatórios): tendem a reduzir entropia real e piorar a experiência.
- Bloquear colar/gerenciadores: incentive gerenciadores de senha; não bloqueie paste.
Exemplo de validação de senha (checklist de back-end)
- Normalizar entrada (ex.: trim apenas se sua política não permitir espaços nas pontas; caso permita, não remova).
- Validar tamanho mínimo/máximo.
- Checar lista de senhas comuns.
- Checar vazamentos.
- Checar se contém identificadores do usuário (e-mail, username).
- Registrar métricas (sem logar a senha), para calibrar política.
// Pseudocódigo de validação (não logar senha!){ "minLen": 12, "maxLen": 72, "checks": [ "length", "notCommonPassword", "notBreached", "notContainEmailOrUsername" ]}Fluxo de reset de senha (token com expiração, uso único e armazenamento seguro)
Reset de senha é um dos fluxos mais sensíveis: ele precisa ser resistente a vazamento de token, replay (reuso), e enumeração de usuários. A abordagem recomendada é: gerar um token aleatório de alta entropia, armazenar apenas o hash do token no banco, aplicar expiração curta, marcar como usado e invalidar sessões/tokens após a troca.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
Modelo de dados sugerido
| Campo | Descrição |
|---|---|
id | Identificador do reset |
user_id | Usuário alvo |
token_hash | Hash do token (ex.: SHA-256 do token + pepper opcional) |
expires_at | Expiração (ex.: 15–60 min) |
used_at | Timestamp de uso (nulo se não usado) |
created_at | Auditoria |
request_ip | Opcional: auditoria/risco |
request_ua | Opcional: auditoria/risco |
Passo a passo: solicitar reset
- Entrada: usuário informa e-mail (ou username).
- Resposta uniforme: sempre responder com sucesso genérico, independentemente de o usuário existir.
- Se existir: criar registro de reset com expiração curta e token aleatório.
- Armazenar hash do token (não o token em si).
- Enviar link por e-mail contendo o token (e um identificador do reset, se desejar).
Geração de token: use bytes aleatórios criptograficamente seguros (ex.: 32 bytes) e codifique em Base64URL/hex. Exemplo conceitual:
token = base64url(randomBytes(32))tokenHash = sha256(token + PEPPER)store(tokenHash, userId, expiresAt)Exemplo de request/response seguro: solicitar reset
Request
POST /v1/auth/password/reset/requestContent-Type: application/json{ "email": "ana@example.com"}Response (uniforme)
200 OKContent-Type: application/json{ "message": "Se existir uma conta para este e-mail, enviaremos instruções para redefinir a senha."}Passo a passo: confirmar reset (trocar a senha)
- Entrada: token (e opcionalmente um
reset_id), e a nova senha. - Validar: expiração, não usado, e comparar
token_hashcom hash do token recebido. - Aplicar política de senha: tamanho, comum, vazada, etc.
- Marcar como usado (uso único) e trocar a senha do usuário.
- Invalidar sessões/tokens existentes do usuário após a troca (ex.: incrementando um
token_versionno usuário, ou revogando sessões no servidor). - Responder sem detalhes excessivos (não revelar se token era válido vs. usuário inexistente, quando possível).
Exemplo de request/response: confirmar reset
Request
POST /v1/auth/password/reset/confirmContent-Type: application/json{ "token": "mYk9p7m0cY...base64url...", "new_password": "minha frase longa com 4 palavras"}Response
200 OKContent-Type: application/json{ "message": "Senha atualizada com sucesso."}Erros seguros (sem vazar sinal útil)
Quando o token for inválido/expirado/usado, evite mensagens que ajudem um atacante a testar tokens. Use respostas genéricas e códigos coerentes:
400 Bad Request{ "error": { "code": "INVALID_RESET_TOKEN", "message": "Não foi possível redefinir a senha. Solicite um novo link." }}Detalhes importantes de implementação
- Uso único: marque
used_atno mesmo fluxo transacional da troca de senha para evitar race conditions. - Expiração curta: 15–60 minutos. Para maior segurança, 15–30.
- Hash do token: se o banco vazar, tokens não podem ser usados diretamente. SHA-256 é comum para token aleatório; opcionalmente adicione pepper do servidor.
- Não reutilizar token: ao solicitar novo reset, você pode invalidar resets anteriores (ex.: apagar/expirar todos os resets pendentes do usuário) para reduzir superfície.
- Auditoria: registre eventos (solicitação, confirmação, falha) sem dados sensíveis.
Confirmação de e-mail e alteração de e-mail
Confirmação de e-mail e mudança de e-mail são fluxos que também exigem tokens de uso único e expiração. O objetivo é garantir que o usuário controla o endereço informado e reduzir risco de sequestro de conta via troca de e-mail.
Confirmação de e-mail (após cadastro)
Estratégia: gerar token de verificação, armazenar hash, enviar link. Ao confirmar, marcar email_verified_at.
Request para reenviar confirmação (resposta uniforme):
POST /v1/auth/email/verification/requestContent-Type: application/json{ "email": "ana@example.com"}200 OK{ "message": "Se existir uma conta para este e-mail, enviaremos um link de verificação."}Confirmar verificação:
POST /v1/auth/email/verification/confirmContent-Type: application/json{ "token": "..."}200 OK{ "message": "E-mail verificado com sucesso."}Alteração de e-mail (fluxo recomendado)
- Exigir autenticação para iniciar a troca.
- Confirmar no e-mail novo: enviar token para o novo endereço e só efetivar após confirmação.
- Notificar o e-mail antigo: enviar alerta “se não foi você, proteja sua conta”.
- Opcional: exigir reautenticação recente (ex.: senha/2º fator) para ações sensíveis.
Passo a passo: solicitar mudança de e-mail
- Usuário autenticado envia
new_email. - Back-end cria um registro de “pending email change” com token e expiração.
- Envia link para o novo e-mail com token.
- Envia notificação para o e-mail antigo informando a tentativa.
Request
POST /v1/account/email/change/requestAuthorization: Bearer <access_token>Content-Type: application/json{ "new_email": "ana.novo@example.com"}Response
200 OK{ "message": "Se o e-mail puder ser usado, enviaremos um link de confirmação para o novo endereço."}Confirmar mudança de e-mail
Request
POST /v1/account/email/change/confirmContent-Type: application/json{ "token": "..."}Response
200 OK{ "message": "E-mail atualizado com sucesso."}Cuidados específicos na alteração de e-mail
- Evitar enumeração: se
new_emailjá estiver em uso, não revele diretamente. Responda de forma uniforme e trate internamente. - Bloquear troca para e-mails descartáveis (opcional, conforme produto).
- Invalidar sessões/tokens após troca de e-mail (ação sensível), ou ao menos exigir novo login em dispositivos não confiáveis.
Proteção contra enumeração de usuários (mensagens uniformes e tempos consistentes)
Enumeração acontece quando um atacante consegue descobrir se um e-mail/usuário existe a partir de diferenças na resposta. Para reduzir isso:
- Mensagens uniformes em endpoints como: solicitar reset, reenviar verificação, iniciar troca de e-mail.
- Status code consistente: frequentemente
200 OKmesmo quando não existe conta. - Tempo de resposta: evite diferenças grandes (ex.: retornar instantâneo quando não existe e demorar quando existe). Você pode introduzir pequenas esperas uniformes ou tornar o caminho “não existe” semelhante (sem fazer operações caras).
- Não expor campos como “e-mail não cadastrado” em validações públicas.
Exemplos de respostas uniformes
Solicitar reset
200 OK{ "message": "Se existir uma conta para este e-mail, enviaremos instruções para redefinir a senha."}Reenviar verificação
200 OK{ "message": "Se existir uma conta para este e-mail, enviaremos um link de verificação."}Iniciar troca de e-mail (autenticado)
200 OK{ "message": "Se o e-mail puder ser usado, enviaremos um link de confirmação para o novo endereço."}Checklist de segurança para políticas de senha e recuperação
- Senha: mínimo 12, máximo definido, permitir passphrases, bloquear comuns, checar vazamentos, evitar regras rígidas de composição.
- Reset: token aleatório, hash no banco, expiração curta, uso único, invalidar sessões/tokens após troca.
- E-mail: confirmação com token hash + expiração; mudança de e-mail com confirmação no novo e notificação no antigo.
- Enumeração: mensagens e status uniformes, cuidado com timing e com detalhes em erros.
- Auditoria: registrar eventos (solicitação/uso) sem dados sensíveis; monitorar volume anormal.