シングルサインオン(SSO)を使用すると、別のサイトから Discourse のユーザー認証を処理できます。DiscourseConnect の実装方法の詳細については、Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso) のトピックをご覧ください。
問題点
DiscourseConnect を使用すると、外部ウェブサイトから Discourse にログインした際に、Discourse ユーザーが作成または更新されます。しかし、ユーザーがサイトにログインすることなく、Discourse ユーザーを作成または更新する必要がある場合は対応できません。DiscourseConnect を使用しているサイトでは、これらのケースは、認証された POST リクエストを sync_sso ルートに送信することで処理する必要があります。
Discourse API gem を使用している場合は、以下のコードの代わりに gem の
sync_ssoメソッドを使用できます。メソッドの使い方は、examples ディレクトリをご覧ください。
例として、親サイトでユーザーがグループに追加され、DiscourseConnect で最初にログインすることなく、Discourse 上の対応するグループに追加する必要があるケースを考えます。ウェブサイトとフォーラム双方のグループ名は「eurorack」です。ユーザーの external_id は 1、メールアドレスは bob@example.com です。以下のコードは PHP を使用していますが、基本的な考え方はどのプログラミング言語にも適用できます。
API 認証情報と SSS シークレットキーの設定
$api_key = '4fe83002bb5fba8c9a61a65e5b4b0a3cf8233b0e4ccafc85ebd6607abab4651a';
$api_username = 'system';
$discourse_connect_secret = 'jdhb19*Xh3!nu(#k';
SSO パラメータの設定
利用可能なパラメータを確認するには、discourse_connect_base.rb の ACCESSORS セクションをご覧ください。既存のユーザーを更新するために 必須 のパラメータは external_id です。Discourse にまだ存在しないユーザーに対して sync_sso を呼び出す場合は、username と email パラメータを含める必要があります。Discourse は、新しいユーザーを作成するために username と email を使用します。
ユーザーをグループに追加するには add_groups パラメータを含め、グループから削除するには remove_groups パラメータを含めます。これらのパラメータの値は、グループ名をカンマで区切った文字列に設定する必要があります。グループ名の間にスペースは使用できません。
![]()
require_activationパラメータがペイロードに含まれています。ユーザーのメールアドレスが親サイトで検証されていない場合はtrueに設定してください。PHPの場合、数値の1に変換されないよう、このパラメータは文字列の'true'に設定する必要があります。ユーザーのメールアドレスが検証済みの場合は、このパラメータを含める必要はありません。
// 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 overrides および discourse connect overrides サイト設定の値が尊重されます。例えば、sync_sso へのリクエストで既存ユーザーのメールアドレスを更新するには、auth overrides email 設定を有効にする必要があります。関連する設定は以下の通りです:
auth overrides emailauth overrides usernameauth overrides namediscourse connect overrides avatardiscourse connect overrides biodiscourse connect overrides groupsdiscourse connect overrides profile backgrounddiscourse connect overrides card backgrounddiscourse connect overrides locationdiscourse connect overrides website
さらなる参考資料
実際の動きを確認するには、sync_sso コード、DiscourseConnectBase の parse メソッド、および DiscourseConnect の lookup_or_create_user メソッドをご覧ください。
Node.js を使用している方のために、このガイドの JavaScript 版 も用意されています。