那么你想使用 Discourse 作为你自己的 Web 应用程序的身份提供商?太棒了!让我们开始吧。
启用 DiscourseConnect 提供商设置
在 Discourse 管理网站设置(/admin/site_settings)中,启用设置 enable discourse connect provider,并在 discourse connect provider secrets 中添加一个密钥字符串(用于哈希 SSO 有效负载)。
在你的 Web 应用程序中实现 DiscourseConnect:
-
生成一个随机的 nonce。我们称这个值为
NONCE。暂时保存它,以便你可以用响应中返回的 nonce 值进行验证。 -
创建一个包含
NONCE和RETURN_URL(Discourse 在验证后将用户重定向到的位置)的新有效负载。有效负载应如下所示:nonce=NONCE&return_sso_url=RETURN_URL。RETURN_URL的主机名必须与你在配置discourse connect provider secrets时使用的域模式匹配。 -
对上述原始有效负载进行 Base64 编码。我们称这个有效负载为
BASE64_PAYLOAD -
对上述
BASE64_PAYLOAD进行 URL 编码。我们称这个有效负载为URL_ENCODED_PAYLOAD -
使用你的 sso 提供商密钥作为密钥,从
BASE64_PAYLOAD生成一个 HMAC-SHA256 签名,然后将此签名转换为小写的十六进制字符串。我们称这个签名为HEX_SIGNATURE
向 Discourse 发送身份验证请求
将用户重定向到 DISCOURSE_ROOT_URL/session/sso_provider?sso=URL_ENCODED_PAYLOAD&sig=HEX_SIGNATURE
从 Discourse 接收响应:
如果以上步骤正确完成,Discourse 将把已登录的用户重定向到提供的 RETURN_URL。你将收到带有 sig 和 sso 以及一些用户信息查询字符串参数。现在请遵循以下步骤:
-
使用 sso 提供商密钥作为密钥,对
sso计算 HMAC-SHA256。 -
将
sig从其十六进制字符串表示形式转换回字节。 -
确保上述两个值相等。
-
Base64 解码
sso;你将得到传入的嵌入式查询字符串。这将有一个名为nonce的键,其值应与最初传入的 nonce 匹配。请确保情况属实,并务必从你的系统中删除该 nonce。 -
你会发现此查询字符串还包含一堆用户信息。按你认为合适的方式使用它们。
就是这样。到目前为止,你应该已经设置好 Web 应用程序以使用 Discourse 作为 SSO 提供商了!
更多参数,更多选项
除了 nonce 和 return_sso_url 之外,请求有效负载还有几个可选参数。
-
prompt: 如果prompt=none,则 SSO 请求被视为“仅检查”请求。如果浏览器/设备已登录到 Discourse,Discourse 将像往常一样返回带有用户身份验证信息的成功 SSO 响应。如果浏览器/设备尚未登录,Discourse 将不会要求用户登录,并将立即返回一个带有参数failed=true的 SSO 响应,而不是用户信息。这提供了一种查询用户是否已登录的机制,而无需在用户未登录时将用户重定向到登录对话框。 -
logout: 如果logout=true,则 SSO 请求将变为_注销_请求。如果用户在该浏览器/设备上登录了 Discourse,他们将被在该设备上注销。无论哪种情况,Discourse 都将立即重定向回return_sso_url,不在查询字符串中添加sso或sig。 -
require_2fa: 如果require_2fa=true,Discourse 将要求用户在重定向回之前验证双因素身份验证(2FA)。响应有效负载将包含confirmed_2fa=true(如果用户成功完成 2FA 验证),或no_2fa_methods=true(如果用户没有配置 2FA 方法)。
prompt=none 和 logout=true 是互斥的;在同一请求中提供两者没有意义。
sso= 有效负载参考
请求参数:
nonce:(字符串,必需)一个安全生成的随机字符串return_sso_url:(字符串,必需)重定向回时附带响应的 URLprompt:(字符串,可选)如果为none,则在不提示用户登录的情况下探测身份验证状态。logout:(布尔值,默认为false)如果为true,则将用户从 Discourse 注销。require_2fa:(布尔值,默认为false)如果为true,则要求用户在重定向回之前验证双因素身份验证。
结果参数:
- 对于注销请求,响应中没有
sso=有效负载或签名,只有一个重定向到请求的纯return_sso_url。 - 登录请求的结果有效负载将始终包含从请求中反射回来的
nonce。 - 结果有效负载还将反映任何其他请求参数。不要依赖此行为;它不一定是故意的,也不是 API 的保证方面。(例如,为什么
return_sso_url参数会被复制到发送到return_sso_url的有效负载中?) - 如果请求未能验证用户,结果有效负载将包含
failed=true。 - 如果请求成功验证了用户,结果有效负载将包含用户凭据/信息:
external_id:(字符串)Discourse 用户 IDusername:(字符串)用户名/句柄name:(字符串)用户的真实姓名email:(字符串)电子邮件地址avatar_url:(字符串)用户上传的头像图片的完整 CDN URLadmin:(布尔值)如果用户是管理员,则为true,否则为falsemoderator:(布尔值)如果用户是版主,则为true,否则为falsegroups:(字符串)用户所属的用户组(按名称)的逗号分隔列表profile_background_url:(字符串)用户个人资料背景图片的完整 CDN URLcard_background_url:(字符串)用户卡片背景图片的完整 CDN URLconfirmed_2fa:(布尔值)如果用户完成了 2FA 验证,则为true(仅在请求require_2fa=true时存在)no_2fa_methods:(布尔值)如果用户没有配置 2FA 方法,则为true(仅在请求require_2fa=true时存在)
如果用户未设置这些项,则可能缺少 name、avatar_url、profile_background_url 和 card_background_url。(Discourse 中任何值为 nil 的元素都将从响应中省略。)
Discourse 官方“将 Discourse 用作身份提供商”实现:
- 一个使用 Discourse SSO 验证用户的 http 代理(使用 golang)(仅限管理员):https://github.com/discourse/discourse-auth-proxy(由 @sam 制作)
社区贡献的“将 Discourse 用作 SSO 提供商”实现:
-
一个实现 Discourse 作为 SSO 提供商的 PHP 脚本:https://gist.github.com/paxmanchris/e93018a3e8fbdfced039(由 @paxmanchris 制作)
-
Erlang:
https://github.com/reverendpaco/discourse-as-sso-erlang -
Node.js:
GitHub - edhemphill/passport-discourse: A Passport strategy for authenticating using a Discourse forum · GitHub
GitHub - ArmedGuy/discourse_sso_node: npm package for Discourse SSO login features. · GitHub -
ASP.NET Core(仅需要配置):
GitHub - Biarity/DiscourseSso: Easy, configurable Discourse SSO: GET /auth/login -> recieve a JWT with user data · GitHub -
MediaWiki 扩展(PHP):
DiscourseSsoConsumer, a SSO extension for MediaWiki @mdoggydog 制作)
