通过 sync_sso 路由同步 DiscourseConnect 用户数据

单点登录(Single Sign On)可用于从独立网站处理 Discourse 用户认证。有关如何实现 DiscourseConnect 的详细信息,请参阅主题:https://meta.discourse.org/t/official-single-sign-on-for-discourse-sso/13045。

问题所在

使用 DiscourseConnect 时,当用户从您的外部网站登录到 Discourse 时,会创建或更新 Discourse 用户。但它无法处理您需要在用户未登录到您网站的情况下创建或更新 Discourse 用户的情况。对于使用 DiscourseConnect 的网站,这些情况应通过向 sync_sso 路由发送经过身份验证的 POST 请求来处理。

:information_source: 如果您正在使用 Discourse API gem,可以使用该 gem 的 sync_sso 方法,而无需使用以下代码。有关如何使用该方法的说明,请参阅 示例 目录。

举个例子,假设父站点上将用户添加到了一个群组,而您需要将该用户添加到 Discourse 上对应的群组中,且无需他们先通过 DiscourseConnect 登录。网站和论坛上的群组名称均为 ‘eurorack’。用户的 external_id1,电子邮件为 bob@example.com。以下代码使用 PHP 编写。基本思路可应用于任何编程语言。

设置您的 API 凭据和 SSO 密钥

$api_key = '4fe83002bb5fba8c9a61a65e5b4b0a3cf8233b0e4ccafc85ebd6607abab4651a';
$api_username = 'system';
$discourse_connect_secret = 'jdhb19*Xh3!nu(#k';

设置 SSO 参数

要查看可用的参数,请查看 discourse_connect_base.rb 中的 ACCESSORS 部分。要更新现有用户,您必须包含的参数是 external_id。如果您为尚未存在于 Discourse 上的用户调用 sync_sso,则必须包含 usernameemail 参数。Discourse 将使用 usernameemail 来创建新用户。

要将用户添加到群组,请包含 add_groups 参数。要从群组中移除用户,请包含 remove_groups 参数。这两个参数的值必须设置为以逗号分隔的群组名称字符串。群组名称之间不允许有空格。

:information_source: 有效载荷中包含了 require_activation 参数。如果用户在父站点上的电子邮件尚未验证,则应将其设置为 true。在 PHP 中,该参数需要设置为字符串 ‘true’,以避免其被转换为数字 1。如果您已验证用户的电子邮件地址,则无需包含此参数。

// 创建 SSO 参数数组。
$sso_params = array(
    'external_id' => 1,
    'email' => 'bob@example.com',
    'username' => 'bob',
    'add_groups' => 'eurorack',
    'require_activation' => 'true',
);

// 将 SSO 参数转换为 SSO 有效载荷并生成 SSO 签名。
$sso_payload = base64_encode( http_build_query( $sso_params ) );
$sig = hash_hmac( 'sha256', $sso_payload, $discourse_connect_secret );

发送 POST 请求

在此示例中,我将使用 curl,将 user_agent 设置为 ‘WordPress/4.9.4’,并将论坛 URL 设置为 https://forum.example.com

$url = 'https://forum.example.com/admin/users/sync_sso';
$post_fields = array(
    'sso' => $sso_payload,
    'sig' => $sig,
);
$headers = array("Content-Type: multipart/form-data;","Api-Key: $api_key","Api-Username: $api_username",);

$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $post_fields ) );
curl_setopt( $ch, CURLOPT_USERAGENT, 'WordPress/4.9.4' );

$result = curl_exec( $ch );

if ( curl_errno( $ch ) !== 0 ) {
    // 处理错误,调用 curl_close( $ch ) 并返回。
}

curl_close( $ch );

$discourse_user = json_decode( $result );

更新现有用户

sync_sso 路由发出的请求将以与用户通过 DiscourseConnect 登录到网站时相同的方式更新现有用户的属性。这意味着您的站点的 auth overridesdiscourse connect overrides 站点设置值将被这些请求所尊重。例如,要通过 sync_sso 请求更新现有用户的电子邮件地址,需要启用 auth overrides email 设置。以下是相关设置:

  • auth overrides email
  • auth overrides username
  • auth overrides name
  • discourse connect overrides avatar
  • discourse connect overrides bio
  • discourse connect overrides groups
  • discourse connect overrides profile background
  • discourse connect overrides card background
  • discourse connect overrides location
  • discourse connect overrides website

进一步阅读

要了解具体运作情况,请查看 sync_sso 代码DiscourseConnectBaseparse 方法以及 DiscourseConnectlookup_or_create_user 方法。

对于使用 Node.js 的用户,本指南还有一个 JavaScript 版本

32 个赞
Sync DiscourseConnect user data with the sync_sso route [JavaScript]
/admin/users/sync_sso ... Route not found
SSO_SYNC not working
Using the API to create a user on an SSO only system
SSO integration & external profile sync help
Creating Discourse accounts via SSO without visiting the forum URL?
Sync_sso post suddenly resulting in 404 not found after succesfully adding a portion of the users
Changing avatar_url while sso_overrides_avatar is set?
"push" sso users to discourse?
Groups API - manually syncing group membership?
SSO_SYNC not working
PHP/API to check whether user exists (by email) and is in specific group
Pre-create user accounts for SSO users
User profile page by id?
DiscourseConnect Provider Questions
Logging in discourse using API - using discourse as API server only
I cannot add user to the discouse forum from a wordpress website when user added in a membership
Integration into custom auth system where emails are not unique?
:cn: Synchronizing DiscourseConnect user data using sync_sso [Java] | 使用 sync_sso 同步 DiscourseConnect 用户数据 [Java]
Letting users choose whether to show Full Name
Auto-provisioning user accounts when SSO is enabled
Creating Discourse accounts during user import
Refresh sso groups
/admin/users/sync_sso 403 Forbidden
Triggering automatic authentication via SSO when linking to private topics?
"BAD CSRF" when executing PUT using API, curl, and PHP
Delete user avatar by API
Delete user avatar by API
Help me troubleshoot my Discourse SSO
Adding existing (and inviting new) users to a group
Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso)
DiscourseConnect, SSO and E-Mail address confirmation
AUTOMATIC: Inviting every new SaaS signup into the Discourse Forum
Question necromancy: migrating from mattermost
Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso)
How to "intercept" first time SSO usages to let users confirm the SSO action and set a username?
API Create user external_ids parameter
First time login for a user using API KEY
How to use Discourse Connect (SSO) to update avatar, username, name?
How to set language for SSO users
What are your experiences with wp-discourse plugin and DiscourseConnect?

收到此消息:{“failed”:“失败”,“message”:“登录错误”}