このドキュメントでは、DiscourseConnect プロバイダーサイトで、ユーザーを Discourse にログインさせ、特定の Discourse URL にリダイレクトするリンクを作成する方法を説明します。
必要なユーザーレベル: 管理者
DiscourseConnect を使用しているサイトでは、DiscourseConnect プロバイダーサイトに、ユーザーを Discourse にログインさせ、特定の Discourse URL にリダイレクトするリンクを追加できます。これは、return_path パラメータがユーザーに最終的に表示させたい Discourse ページのパスに設定された /session/sso ルートを指すリンクを作成することで実現されます。
リンクの href プロパティは以下の形式である必要があり、\<相対パス\> の部分をユーザーに最終的に表示させたいパスに置き換えます。
https://forum.example.com/session/sso?return_path=く相対パス>
ユーザーをログインさせ、Discourse サイトのホームページにリダイレクトするアンカータグの例:
<a href="https://forum.example.com/session/sso?return_path=/">コミュニティ</a>
ユーザーをログインさせ、「トップトピック」ページにリダイレクトするアンカータグの例:
<a href="https://forum.example.com/session/sso?return_path=/top">トップトピック</a>
Discourse での return_path の保存方法
Discourse は、return_path パラメータの値を、ユーザーが /session/sso ルートにアクセスしたときに生成される SSO ノンス (nonce) をキーとしてサーバーセッションに保存します。DiscourseConnect 認証プロセスの最後に、Discourse はノンスを使用して return_path を検索し、ユーザーをそのパスにリダイレクトします。
認証済みユーザーにとってプロセスをシームレスにする方法
ユーザーが Discourse の /session/sso ルートにアクセスすると、discourse connect url サイト設定で設定された URL にリダイレクトされます。その後、DiscourseConnect プロバイダーは、ユーザーが Discourse の ログイン ボタンをクリックした場合とまったく同じ方法で認証プロセスを処理します。
認証プロバイダーサイトで既にログインしているユーザーに対して認証プロセスをシームレスにするには、認証プロバイダーの DiscourseConnect コードで、ユーザーがログインしているかどうかを確認する必要があります。ユーザーがログインしていない場合は、認証プロバイダーサイトでのログインプロセスに進めます。ユーザーが既にログインしている場合は、認証プロバイダーサイトでのログインプロセスをスキップします。
ここでは、WP Discourse プラグイン のコードを使用したコメント付きの例を示します。これは、認証済みユーザーと未認証ユーザーをどのように異なる方法で処理できるかを示しています。
public function sso_parse_request( $wp ) {
// プラグインオプションでシングルサインオン (SSO) が有効になっているかを確認
if ( empty( $this->options['enable-sso'] ) ) {
return null;
}
// 続行する前にログアウト要求を処理
$this->handle_logout_request();
// クエリ変数に 'sso' および 'sig' パラメータが存在するかどうかを確認
if ( array_key_exists( 'sso', $wp->query_vars ) && array_key_exists( 'sig', $wp->query_vars ) ) {
// 'sso' ペイロードと署名をサニタイズして、安全に使用できるようにする
$payload = sanitize_text_field( $wp->query_vars['sso'] );
$sig = sanitize_text_field( $wp->query_vars['sig'] );
// WordPress にログインしていない場合、ログインページにリダイレクトする
// これにより、アクティブなセッションがないユーザーは最初に WordPress にログインするように求められる
if ( ! is_user_logged_in() ) {
// ログイン後にリダイレクトするための URL を構築
$redirect = add_query_arg( $payload, $sig );
// リダイレクトパラメータを使用して WordPress のログイン URL を生成
$login = wp_login_url( esc_url_raw( $redirect ) );
// ログインリダイレクトの前にアクションをトリガーする(ロギングやカスタムアクションにオプション)
do_action( 'wpdc_sso_before_login_redirect', $redirect, $login );
// WordPress のログインページにリダイレクト
return $this->redirect_to( $login );
} else {
// ユーザーが既に WordPress で認証されている場合、ログインプロセスをバイパスし、
// SSO ペイロードと署名の検証に進む。
$sso_secret = $this->options['sso-secret'];
$sso = new SSO( $sso_secret );
// SSO シークレットを使用してペイロードと署名を検証
if ( ! ( $sso->validate( $payload, $sig ) ) ) {
// 無効な SSO リクエストを処理
return $this->handle_error( 'parse_request.invalid_sso' );
}
// 現在ログインしている WordPress ユーザーを取得
$current_user = wp_get_current_user();
// ログインしているユーザーデータを使用して SSO パラメータを準備
$params = $this->get_sso_params( $current_user );
try {
// ペイロードからノンスを生成し、SSO ログイン文字列を構築
$params['nonce'] = $sso->get_nonce( $payload );
$q = $sso->build_login_string( $params );
} catch ( \Exception $e ) {
// SSO パラメータ生成に問題がある場合の例外を処理
return $this->handle_error( 'parse_request.invalid_sso_params', array( 'message' => esc_html( $e->getMessage() ) ) );
}
// SSO ログインのためにユーザーをリダイレクトする前にアクションをトリガー(ロギングに役立つ)
do_action( 'wpdc_sso_provider_before_sso_redirect', $current_user->ID, $current_user );
// 詳細な SSO ログが有効な場合に SSO 成功を記録
if ( ! empty( $this->options['verbose-sso-logs'] ) ) {
$this->logger->info( 'parse_request.success', array( 'user_id' => $current_user->ID ) );
}
// 認証済みユーザーを、SSO ログイン文字列付きの DiscourseConnect ログイン URL にリダイレクト
return $this->redirect_to( $this->options['url'] . '/session/sso_login?' . $q );
}
}
// リクエストに SSO パラメータが見つからない場合は null を返す
return null;
}
return_path を非 Discourse URL に設定する
Discourse では、ユーザーをログインさせて非 Discourse URL にリダイレクトさせることが可能です。これを機能させるには、discourse connect allowed redirect domains サイト設定にドメインを追加する必要があることに注意してください。デフォルトでは、この設定は空白であり、非 Discourse URL へのリダイレクトを防いでいます。ワイルドカードとして * を使用してすべてのドメインを許可することもできます。これを有効にする場合は、ユーザーをリダイレクトさせたい非 Discourse URL の場合は、return_path パラメータに絶対 URL を使用するようにしてください。