Describa el error
Cuando se utiliza Discourse como un Proveedor de DiscourseConnect (Proveedor SSO), la dirección de correo electrónico del usuario se expone en la URL de redirección 302 al relying party (parte que confía). Esto sucede porque el método populate_user_data en lib/second_factor/actions/discourse_connect_provider.rb siempre establece el correo electrónico:
def populate_user_data(sso)
sso.name = current_user.name
sso.username = current_user.username
sso.email = current_user.email # <-- Siempre incluido
sso.external_id = current_user.id.to_s
# ...
end
Este correo electrónico se codifica en Base64 y se incluye en la URL de redirección:
https://sitio-destino.com/callback?sso=<payload_base64>&sig=<firma_hmac>
La decodificación del payload base64 revela la dirección de correo electrónico en texto plano.
Impacto
- Historial del navegador: El correo electrónico se registra en el historial del navegador
- Registros de Nginx: La URL completa se registra en los registros de acceso de nginx
- Registros del sitio de destino: El relying party recibe el correo electrónico sin consentimiento explícito del usuario
- Expectativa del usuario: Los usuarios normalmente autorizan para demostrar “Soy un usuario legítimo”, no esperan que se comparta su correo electrónico
Comportamiento esperado
Los usuarios deben poder controlar si su correo electrónico se comparte con el relying party. Debería haber una opción de configuración similar a discourse_connect_overrides_groups, discourse_connect_overrides_avatar, etc.
Actualmente no hay una configuración del sitio para deshabilitar este comportamiento. Escribir un plugin para anular este comportamiento es posible pero no es lo ideal.
Pasos para reproducir
- Habilitar
enable_discourse_connect_provider - Configurar
discourse_connect_provider_secrets(ej. *.example.com|secret123) - Hacer que un usuario se autentique a través del Proveedor DiscourseConnect
- Comprobar la URL de redirección 302: el correo electrónico es visible en los parámetros de la URL
La URL de redirección se ve así:
https://relying-party.com/sso?sso=bm9uY2U9xxx&sig=xxx
La decodificación del parámetro sso revela:
nonce=xxx&return_sso_url=xxx&email=user@example.com&external_id=123
Entorno
- Versión de Discourse: (más reciente)
- Autohospedado
Sugerencias de posibles soluciones
- Añadir una configuración del sitio como
discourse_connect_provider_includes_email(predeterminado: true para compatibilidad con versiones anteriores) para controlar si el correo electrónico se incluye en la respuesta - O implementar el callback basado en POST en lugar de la redirección GET 302 para evitar el registro de la URL