Discourse のメンバーがログアウトされる - 修正方法は?

こんにちは。私のフォーラムのメンバー数名が、20〜30 分後に自動的にログアウトされてしまうという報告を受けています。

SSO を使用しているため、以下のようなフローで問題が起きているのではないかと考えています。メインサイトにログインし、Discourse に入ると(そこで新しいセッションが開始される?)、その後メインサイトに戻ると(Discourse はアイドル状態になる)、再び Discourse に入ると何らかの理由でログアウトされてしまう、と。

(しかし、これは少し理にかなっていません。Discourse にアクセスするたびに「アイドルタイムアウト」が 0 にリセットされるはずだからです。)

メタフォーラムでタイムアウトに関するスレッドをいくつか見つけましたが、明確な答えは見つかりませんでした。

質問:メンバーが X 時間アイドル状態になるまでログアウトされないようにする設定はありますか?それが見つかりません。

Discourse の設定で「最大セッション期間」を 1 時間に設定しているのは確認できましたが、SSO 実装においてはこれが実際には関係ないのではないかと思っています。(なお、メンバーがメインサイトからログアウトする際は、整合性を保つために Discourse へ /logout メッセージを送信しています。また、メンバーが Discourse でどのような活動を行っても、メインサイト上の最終活動時刻を更新しているため、メインサイト側のタイムアウトが原因ではないはずです。これが正常に機能しているか確認するために、現在追加のデバッグコードを追加しています。)

ありがとうございます
E

SSO にも適用されますので、おそらく問題の原因はそこにあるでしょう。1 時間無操作が続くと Discourse のセッションが終了し、ユーザーは再度 SSO で認証を行う必要があります。

問題ありませんし、完全に正常な動作です。1 時間の非活動後にはログアウトされるはずです。

問題は、20〜30 分でログアウトされるという報告が寄せられていることです。

その 1 時間のアイドルタイムアウトに関する設定はありますか?最初の投稿でも述べたとおり、それが見つからないのですが、まずはそこを確認するのが妥当だと思われますよね?

最も明らかな原因を除外するために確認ですが、時間が正確でなかった可能性はありませんか?30 分と 1 時間はそれほど違いませんしね :wink:

このデバッグを続けるためには、次に user_auth_tokens テーブルと user_auth_token_logs テーブルで利用可能なデータを確認することをお勧めします。これらには、セッショントークンと有効期限に関するすべての情報が含まれています。

はい、OP であなたが言及していたものです。

同意します :wink: 今すぐテストしています。サイトにログインして、フォーラムに移動し、そのままブラウザを放置しています!

データベーステーブルに関するアドバイスありがとうございます。さらに調査します。

ふむ。ユーザーがフォーラムを利用し、トピックを読むなどして、投稿の作成(create_post)、トピックの作成(create_topic)、投稿の編集(edit_post)など、何らかのアクションを起こすと、Webhook を通じて通知が届きます。これにより、メインサイトはユーザーがまだアクティブであると判断し、セッションの「最終クリック」値を更新してログアウトを防ぐことができます。これは本来の動作通りで、問題ありません。

しかし、メンバーが単にメッセージを読み続けているだけの場合、Discourse のアイドル時間はリセットされます(これは良いことです)が、メインサイトにはユーザーがアクティブであることを示す Webhook メッセージが一切届きません。そのため、1 時間何のアクションも取らないと(フォーラムに行って PC から離れてしまったように見える)、メインサイトはユーザーが切れたと判断し、ログアウトしてしまいます。

ここにはロジック上の穴があるように思えます。適切な SSO 実装を行うのであれば、Discourse からユーザーのセッションがアクティブかどうか(単に閲覧しているだけでも)を通知する仕組みがあるべきではないでしょうか?例えば、メンバーがアクティブだが他の Webhook メッセージを生成していない場合に、5 分ごとにピングを送信するなどの対応が考えられます。

あるいは、私のサイト側でユーザーのタイムアウトを判断した時点で、Discourse に問い合わせて、そちらでユーザーがアクティブかどうかを確認する方法もあるかもしれません。そのようなことは可能でしょうか?(Is there an endpoint to check if a user is logged in - #3 by pfaffman という記事を見つけましたが、これが求めているものかどうかはっきりせず、/session/current.json は API ドキュメントに記載されていません。)ただし、これでは API 呼び出しが膨大になってしまいます。私のサイトでは、アイドル状態により毎分約 15〜20 人のユーザーをログアウトさせているため、その都度呼び出しを行うことになり、Discourse ID のローカルキャッシュがない場合はさらに多くの呼び出しが必要になる可能性があります。

皆さん、どのようにお考えですか?アドバイスをお願いします。

すべてのプロフィールエンドポイントには last_seen 値があり、これを使用できます。

私は SSO プロトコルでこのような設定を見たことがなく、このような機能のリクエストも受けたことがありません。一般的には、2 つのシステムを独立して運用するのが普通です。

本当に「ユーザーが閲覧した」ための webhook を作成したい場合は、カスタムプラグインを使って実現できるかもしれません。

「2つのシステムを独立して運用する」とはどういう意味でしょうか?私が提示した問題を解決する明らかな方法を見落としているかもしれませんので、もしそうであれば教えてください!

それ以外の場合、私の選択肢は以下の通りです:

  1. メインサイトでユーザーがタイムアウトする前にログアウトせず、Discourseに呼びかけてlast_seen値を確認し、メンバーが実際にフォーラムで活動しているか(ただし、Webhook呼び出しを生成するアクションは行っていない)を確認する。利点: 実装が容易。欠点: API呼び出しが大量に発生し、すでにこの点で苦労しており、レート制限を回避する対応に追われています。

  2. 自分専用のプラグインを作成し、定期的にメインサイトにPingを送信することで、メインサイト上のユーザーの最終アクティビティ時刻を更新する。利点: 「正しい」解決策(プッシュメッセージでアクティビティを示す)のように感じられる。ある程度エレガント。欠点: 実装が容易ではない。

  3. メインサイトのログアウト時間を2時間に変更する。利点: 実装が容易。欠点: 何かありますか?

  4. 気にしない。ユーザーはDiscourseセッションの途中でログアウトされ、激しく不満を漏らします。これが現在の状況です。:wink: 利点: 実装が容易、笑。欠点: ユーザーエクスペリエンスが非常に悪い。

何か見落としていませんか?

#3がよい答えのように思えますが、メインサイトでログアウト時間を長くすることの波及効果について考える必要があります。

#1が最善の選択肢だと考えていますが、その場合、これほど多くのレート制限の問題をどう防ぐかを決めなければなりません。Discourse(およびnginx、DiscourseのDockerインストールを使用しているため)ですべてのレート制限をグローバルに無効にする方法があればいいのですが、完全に無効にしたいのです。私はそれらを必要としていません。メインサイトからDiscourseインスタンスへの通信のみです。ユーザーAPIキーは許可しておらず、システムAPIキーを持っているのは私だけです。完全に閉じたシステムであり、レート制限はただ(常に)私の邪魔をしているだけです。これは別の話題かもしれませんが。

ご提示いただいた動作を維持する必要がある場合は、はい、それら 4 つのオプションが該当すると思います。ただし、動作を少し変更すれば、利用可能なツールとの相性がより良くなるでしょう。

あなたの設定で特異な点は以下の通りです:

メインサイトでのセッションが切れるたびに Discourse のセッションを終了させています。この部分を削除すれば、設定は一般的な構成と一致するようになると思います。

ユーザーがメインサイトから明示的にログアウトする際に /logout を呼び出すことは可能です。ただし、セッションが自然に切れた際には呼び出さないようにしてください。

元の投稿からは判断できませんが、超機密情報を共有する専門性の高いサイトを運営しているのか、それとも多くのユーザーが共有された公共のコンピューターからログインしているような状況なのでしょうか?

現状、最もシンプルな解決策は、ユーザーセッションの切捨てや強制ログアウトを過度に積極的に行わないことのように思えます。ユーザーとしての私の希望は、常に「明示的にログアウトボタンをクリックしない限り、決してログアウトさせないでほしい」というものです。それが不可能なら、せめて1日や1週間など、もう少し長い期間に設定することはできませんか?

なるほど、それは良い解決策ですね。ログインページにある「ログイン状態を保持する」チェックボックスを利用するメンバーが十分にいるので、彼らをメインサイトにスムーズに戻せると思います。もしメインサイトでのセッションが期限切れになっていれば、その時点で(見えない形で)自動的に再ログインされるはずです。ふむ。

プライバシーに非常に敏感な層を対象としたサイトです。ただ、おっしゃることは理解できました。あなたと David の提案通りに対応できそうです。

二人とも、本当にありがとうございます。 ここでの「全体像」や、他のサイトがこの種のシナリオをどのように扱っているのか、以前はよくわからなかったのですが、今は理解できました :slight_smile: 私の状況にもいくつかの解決策が見えてきました。心から感謝しています!