描述错误
当使用 Discourse 作为 DiscourseConnect 提供商(SSO 提供商)时,用户的电子邮件地址会暴露在重定向到依赖方的 302 重定向 URL 中。这是因为 lib/second_factor/actions/discourse_connect_provider.rb 中的 populate_user_data 方法总是设置电子邮件:
def populate_user_data(sso)
sso.name = current_user.name
sso.username = current_user.username
sso.email = current_user.email # <-- 总是包含
sso.external_id = current_user.id.to_s
# ...
end
然后,此电子邮件会被 Base64 编码并包含在重定向 URL 中:
https://target-site.com/callback?sso=<base64_payload>&sig=<hmac_signature>
解码 base64 有效负载会以纯文本形式显示电子邮件地址。
影响
- 浏览器历史记录:电子邮件记录在浏览器历史记录中
- Nginx 日志:完整的 URL 会记录在 nginx 访问日志中
- 目标站点日志:依赖方在未经用户明确同意的情况下接收到电子邮件
- 用户预期:用户通常授权是为了证明“我是合法用户”——他们不希望自己的电子邮件被共享
预期行为
用户应该能够控制是否与依赖方共享其电子邮件。应该有一个配置选项,类似于 discourse_connect_overrides_groups、discourse_connect_overrides_avatar 等。
目前没有站点设置可以禁用此行为。编写插件来覆盖此行为是可能的,但并非理想选择。
重现步骤
- 启用
enable_discourse_connect_provider - 配置
discourse_connect_provider_secrets(例如,*.example.com|secret123) - 让用户通过 DiscourseConnect 提供商进行身份验证
- 检查 302 重定向 URL - 电子邮件在 URL 参数中可见
重定向 URL 如下所示:
https://relying-party.com/sso?sso=nonce=xxx&sig=xxx
解码 sso 参数显示:
nonce=xxx&return_sso_url=xxx&email=user@example.com&external_id=123
环境
- Discourse 版本:(最新)
- 自托管
可能的修复建议
- 添加一个站点设置,如
discourse_connect_provider_includes_email(默认为true以向后兼容),以控制是否在响应中包含电子邮件 - 或者,实现基于 POST 的回调而不是 GET 302 重定向,以避免 URL 日志记录