Descreva o bug
Ao usar o Discourse como um Provedor DiscourseConnect (Provedor SSO), o endereço de e-mail do usuário é exposto no URL de redirecionamento 302 para a parte confiável (relying party). Isso ocorre porque o método populate_user_data em lib/second_factor/actions/discourse_connect_provider.rb sempre define o e-mail:
def populate_user_data(sso)
sso.name = current_user.name
sso.username = current_user.username
sso.email = current_user.email # <-- Sempre incluído
sso.external_id = current_user.id.to_s
# ...
end
Este e-mail é então codificado em Base64 e incluído no URL de redirecionamento:
https://site-alvo.com/callback?sso=<payload_base64>&sig=<assinatura_hmac>
A decodificação do payload base64 revela o endereço de e-mail em texto simples.
Impacto
- Histórico do navegador: O e-mail é registrado no histórico do navegador
- Logs do Nginx: O URL completo é registrado nos logs de acesso do nginx
- Logs do site de destino: A parte confiável recebe o e-mail sem consentimento explícito do usuário
- Expectativa do usuário: Os usuários geralmente autorizam para provar “Eu sou um usuário legítimo” - eles não esperam que seu e-mail seja compartilhado
Comportamento esperado
Os usuários devem ser capazes de controlar se seu e-mail é compartilhado com a parte confiável. Deve haver uma opção de configuração semelhante a discourse_connect_overrides_groups, discourse_connect_overrides_avatar, etc.
Atualmente, não há configuração de site para desativar esse comportamento. Escrever um plugin para substituir esse comportamento é possível, mas não ideal.
Etapas de reprodução
- Habilitar
enable_discourse_connect_provider - Configurar
discourse_connect_provider_secrets(ex: *.example.com|secret123) - Fazer um usuário autenticar via Provedor DiscourseConnect
- Verificar o URL de redirecionamento 302 - o e-mail é visível nos parâmetros do URL
O URL de redirecionamento se parece com:
https://parte-confiavel.com/sso?sso=bm9uY2U9xxx&sig=xxx
A decodificação do parâmetro sso revela:
nonce=xxx&return_sso_url=xxx&email=user@example.com&external_id=123
Ambiente
- Versão do Discourse: (mais recente)
- Auto-hospedado
Sugestões de correção possíveis
- Adicionar uma configuração de site como
discourse_connect_provider_includes_email(padrão: true para compatibilidade com versões anteriores) para controlar se o e-mail é incluído na resposta - Ou implementar o callback baseado em POST em vez de redirecionamento GET 302 para evitar o registro do URL