認証によるグループメンバーシップの管理

@david 758082333 のコメントから議論を続けます。

おそらく推測できるかと思いますが、私も openid-connect プラグインに固有の問題ではない、この問題に対する安定した解決策を強く望んでいます。前進できる方法を見つけられるか見てみましょう。

あなたが提起した点について補足します。

ユーザーをどのグループに追加し、どのグループから削除するかをどのように決定しますか?また、それが Discourse 自体で手動にユーザーをグループに追加/削除することにどのように影響しますか?

  1. ユーザーが ['group1', 'group2'] のグループで OIDC 経由で認証する
  2. Discourse の UI で、そのユーザーが group3 に追加される
  3. 後で、同じユーザーが ['group1'] のグループで OIDC 経由で認証する

人間がこれを検証すれば、最終状態は group1, group3group2 は削除されるべき)であることがわかります。しかし、その判断をプログラム的に行うために追跡されている状態が十分ではないと思います。同様に:

  1. ユーザーが ['group1', 'group2'] のグループで OIDC 経由で認証する
  2. Discourse の UI で、そのユーザーが group1 から削除される
  3. 後で、同じユーザーが ['group1', 'group2'] のグループで OIDC 経由で認証する

今度はどうなるべきでしょうか?管理者が明示的にユーザーを group1 から削除しましたが、OIDC が再び追加してしまいました。これは管理者にとって非常に混乱を招く UX です。グループを「外部管理」であると識別する方法が必要かもしれません。そうすれば、追加/削除の UI をすべて非表示にできるかもしれません :thinking:

この問題に対処する方法はいくつか考えられます(これらは排他的ではありません)。

グループとトークン属性の識別

いかなる実装においても、以下の明確な識別が必須となるべきです。

  1. 認証経由でメンバーシップを管理できるグループ
  2. 認証トークン内のどの属性がグループメンバーシップを制御するか

これはサイト設定、グループ設定、その他の方法によるかにかかわらず、デフォルトは「オフ」であるべきです。

厳格または寛容な処理

グループが識別されたトークン属性に存在しない場合、ユーザーが削除される処理は「厳格」です。グループが識別されたトークン属性に存在しない場合でも、ユーザーが削除されない処理は「寛容」です。

厳格/寛容の状態はグループごとに設定されます。サイト設定でこれを行う方法の例はここにあります:https://github.com/discourse/discourse-openid-connect/pull/7/commits/1665bdccbb492788f64ba6844ad6f9ae1a41d95e。同じアプローチをグループ設定で行うことも可能です。

あなたが提案しているように、処理が「厳格」である場合、グループ管理画面経由でのグループメンバーシップの追加/削除を無効にすることもできます。

メンバーシップのソース識別

また、group_users テーブルにグループメンバーシップのソースを保存することで、グループ内で「混合」アプローチを可能にすることも考えられます。つまり、認証トークン経由で作成されたメンバーシップは管理者が削除できないようにするのです。

この件について考えるほど、これはグループ設定を通じて行うべきだと考えるようになっています。

「いいね!」 11

@angus、このトピックを始めてくれてありがとう!この機能に熱心な人はたくさんいると思います!

興味深いですね!私はこれまで、認証中にグループが自動的に作成され、グループ名がアイデンティティプロバイダーのグループ名と 1 対 1 で対応すると想定していました。現在の DiscourseConnect はそのように動作しています。

しかし、実際にはこのより明示的なオプションの方が気に入りました!これにより、アイデンティティプロバイダーから不要なグループが Discourse インスタンスに混入することがなくなり、管理者がグループ名を好みに合わせてカスタマイズできるようになります。これは、既存のメールドメインベースのメンバーシップと非常に多くの共通点を持っています。

技術的な観点からは良さそうです。唯一の懸念は、ユーザーや管理者に説明するのが難しいかもしれないということです。認証管理グループの「明示的な特定」というあなたの案を採用する場合、単に「厳格」な処理を実装すればよいのではないでしょうか?

認証管理に設定されたグループでは、手動での追加/削除は大きな警告の奥に隠され、あなたが説明した「厳格」モードのように動作します。

どう思いますか?

余談ですが、ユーザーの自動的な追加/削除はすべてグループログに記録されるようにすべきです。そうすれば、何が起こっているのか、なぜそうなっているのかを全員が理解しやすくなります。

「いいね!」 7

はい、少なくともこの機能セットの v1 においては、明示的に設定する方がよいと感じます。まだ、自動作成が本当に必要とされるユースケースに出会ったことはありません。つまり、クレームの処理が行われる前に、サイト管理者がグループを設定・構成できるからです。

明示的なバージョンを実装した後、オプションとして自動作成に移行することは可能でしょうか?

グループ設定の観点では、以下のような形になります。

設定セクション: メンバーシップ(既存のセクション)
設定グループタイトル: 認証管理
設定:

  • サービス: 認証サービスのリスト。「すべて」もオプションとして含めます。この設定は、この機能セットの有効化/無効化の状態としても機能します。つまり、デフォルトは「なし」になります。
  • クレーム: ID トークンのクレームを特定するためのテキスト入力。この機能の「説明」(おそらく Meta のこのスレッド内にあるもの)では、サポートされている形式(ブール値、カンマ区切りの文字列など)を説明します。
  • モード: 後述

はい、「厳密」または「許容」の設定がある場合、それを簡潔に説明する必要があります。そのアプローチとしては、「追加」と「削除」に焦点を当てるのがよいと思います。以下のように説明できるかもしれません。

設定: 「モード」

オプション 1(許容):

  • ラベル: 「メンバーの追加」
  • 説明: 「認証時にメンバーをこのグループに追加することを許可する」

オプション 2(厳密):

  • ラベル: 「メンバーの追加と削除」
  • 説明: 「認証時にメンバーの追加と削除の両方を許可する。これにより、手動でのメンバーシップ制御は無効になります。」

「許容」オプションを維持したいと強く考えている理由は、以前この種の作業をクライアントと行った際、最も一般的なユースケースだったからです。つまり、

  • 主なニーズは、外部サービスの状態に応じてグループへのアクセスを許可することです。

  • 外部サービスの状態に応じてアクセスを削除するニーズはより限定的です。つまり、アクセスを失い削除されるべき人はいますが、これは比較的あまり重要ではありません。

  • 往々にして、Discourse 上でメンバーシップを手動で制御できる機能を維持したいという要望があります。「厳密」なアプローチを実装した際、これは(説明を行ったにもかかわらず)「驚き」を招くことがありました(「なぜ X さんがメンバーシップを失ったのか?」など)。しかし、機能としては(技術的に)正常に動作していました。

はい、これは重要です。特に「厳密」モードでは、誰かが追加または削除された理由を人々が疑問に思うことがよくあるからです。また、私たち(つまり「Discourse」)は、外部認証サービスが提示するクレームの真偽を制御することはできません。

そのアクションを担当した認証サービスを含む「ユーザーの削除」と「ユーザーの追加」の新しいアクションタイプを作成するのはどうでしょうか。つまり、「ユーザーの削除([サービス名])」のように。

「いいね!」 3

もう一つ「落とし穴」があります。それは、「外部サービス X に基づいてグループのメンバーシップを管理したい」というユースケースに対して、これが万能ではないことを明確にしておく必要があるという点です。なぜなら、ユーザーは頻繁に認証を行わないため、そのような標準的なユースケースの要件を満たすには不十分だからです。

この認証管理は、そのようなユースケースを処理する上で不可欠な要素ですが、適切に機能させるためには、イベントベースの統合(例えば、ウェブフック受信機)のセットアップも必要です。グループ管理用に設計されたプライベートなウェブフック受信機プラグインを保有しており、近々オープンソース化することを計画しています。

「いいね!」 5

@david この件についてどうお考えですか?もし私がプルリクエストを作成したら、検討していただけますか?

「いいね!」 2

ここで行っている素晴らしいお仕事を心から称賛します! :sunflower:

機能の比較として、Global Legal Empowerment Network で実施している取り組みをご紹介します。同ネットワークでは WordPress と Discourse の WordPress プラグインを活用しています。設定により、WordPress 側でユーザー情報が更新されると、Discourse 側でも自動的に反映される仕組みになっています。これには、コアメンバーやリソース貢献者などの特別グループ、およびプロフィール詳細も含まれます。トラブルシューティングや正常な動作確認を容易にするため、「最終更新日時」を隠しユーザーフィールドとして追加しました。

これらのグループは遠隔管理でロックし、Discourse 上でユーザーが参加・脱退できないようにしています。ただし、スタッフによるグループメンバーシップの管理を制限する必要はないと考えました。あなたが試みているアプローチの見た目には好感を持っていますが、正直なところ私には少し理解が及ばない部分もあります。

Discourse for Teams の顧客の中には、Okta を積極的に活用して自社のすべてのアプリケーションへのアクセスを管理している企業もあります。同社では Okta 上で役割を設定しており、その役割に基づいて Microsoft Tableau へのアクセス権限レベルなどを制御しています。Okta はディレクトリとしても機能するため、ユーザーのアバター、自己紹介文、所在地、その他のプロフィール情報も管理しています。彼らは、Okta 外部からでも Teams 上でこれらのプロフィール情報を更新できるようにしたいと考えています。

「いいね!」 5

可能であれば、グループ設定から超技術的な詳細は除外すべきだと考えます。構文ドキュメントへのリンクが必要になる場合は、それを簡略化するか、管理者サイト設定に任せるべきでしょう。実装方法は認証プラグインによって大きく異なるため、その部分は各認証プラグインに任せるべきだと考えます。

OIDC を例に挙げると、そのプラグインは新しいサイト設定 openid_connect_roles_claim を追加します。Okta を使用する場合、管理者はこれを groups として設定します。OIDC において文字列配列は非常に標準的な形式ですが、本当に必要であればより複雑なオプションを検討することもできます。

この情報を受け取るために、Auth::Result に新しい roles 属性を追加し、単純な文字列の配列を受け取れるようにします。コアはこれを (Auth::Result#apply_user_attributes! 内で) 受け取り、新しい UserAssociatedRoles テーブル (provider_name, user_id, role のカラムを持つ) に読み込みます。この UserAssociatedRoles テーブルにより、OP で言及された「メンバーシップのソース識別」が可能になります。

グループ設定は以下のようなイメージになるでしょう:

ロール名には provider_name がプレフィックスとして付与されます。自動補完は UserAssociatedRoles テーブル内の既存のすべての値に基づきますが、Discourse がまだロールを検知していない場合のために、自動補完されていない値の入力も受け付けるようにします。

データベース内に完全な user_associated_roles テーブルを持つことの利点は、管理者が Discourse グループに対して何を行っても、メンバーシップが即座に更新され、ユーザーが再度ログインする必要がなくなることです。

その通りです。少なくとも v1 では、これを可能な限りシンプルに保つのが最善だと考えます。そのため、複数の「モード」を用意するのは避けたいです。デフォルトの動作を以下のようにするのはどうでしょうか:

  • 認証プロバイダーから一致するロールを持つユーザーをメンバーに追加
  • そのロールが失われた場合にメンバーを削除
  • Discourse 上での追加/削除も許可
  • 管理者が認証プロバイダー経由で追加されたユーザーを削除しようとした場合、「このユーザーは次回ログイン時に再度追加される可能性があります」という警告を表示

ここではデフォルトでセキュリティを優先し、ID プロバイダーでロールが失われた場合にメンバーを削除すべきだと考えます。メンバーシップログの改善により、現在の状況よりも混乱が少ないはずです。

それを望まないサイトのために、remove_group_membership_when_auth_role_lost(デフォルトは true)のようなサイト設定を用意することもできます。

その通りです。名前やアバターなど、他のユーザーメタデータについても同様の問題があります。近い将来、他の認証プラグイン向けに sync_sso と同等の機能を実装する必要があると考えています。これには、通常 OIDC / SAML などで渡されるすべての情報(この新しい「ロール」情報を含む)を渡せるようにします。ただし、これはおそらく別のプロジェクトになるでしょう。


すべていかがでしょうか、@angus?厳格/許容モードを分けるよりも少し柔軟性は低下しますが、モードを一つに統一することでトラブルシューティング、ドキュメント、サポートが格段に楽になると考えます。


その計画に基づき、管理者の視点からの高レベルな概要は以下の通りです:

初期設定

  1. Okta 認証を設定し、Okta 側で groups クレームを有効化 します
  2. Discourse 側で openid_connect_roles_claimgroups に設定します

新しいグループの設定

  1. 通常通り Discourse グループを作成します。名前、フルネーム、フレアなどを好きなように設定します

  2. 「メンバーシップ」設定に移動し、SSO ロールドロップダウンにカーソルを合わせてロールを選択します。Discourse がまだそのロールでログインしたユーザーを見ていない場合は、手動で入力する必要があります

    1 つの Discourse グループに対して複数のロールを指定できます。例えば、Discourse 上の「チーム」グループは oidc:employeesoidc:contractors の組み合わせにすることができます

  3. 保存を押すと、Discourse が過去のログインからキャッシュしているロール情報に基づいて、グループメンバーシップが即座に更新されます

  4. 今後のログインでは、ID プロバイダー側のロール変更が Discourse グループに反映されます

  5. ネイティブの Discourse UI でユーザーの追加/削除を行うことも可能です

    • ID プロバイダー経由で追加されたユーザーを削除しようとした場合、「ユーザーは次回ログイン時に再度追加される可能性があります」という警告が表示されます
  6. 後で、その IDP ロールをグループに関連付けたくないと感じた場合は、それを削除できます。そのロールを通じてメンバーだったすべてのユーザーも削除されます

「いいね!」 2

同意します。

はい、その通りです。ただし、ブール値のクレームをサポートするケースも存在します。とはいえ、まずは文字列配列のみをサポートすることでシンプルに保つことに賛成です。

各認証プロバイダーごとに実装するとすれば、Auth::Authenticatorgroup_sync_enabled? メソッドを定義し、個々の認証プロバイダーや、関連設定に値が存在する汎用認証プロバイダーでオーバーライドする形になるでしょうか。

これは興味深い問いを投げかけています。この仕組みは、Facebook(「groups」?)、Google(「groups」?)、Discord(「roles」?)などの特定のサービス認証プロバイダーでも利用可能になるかもしれません。ID トークンにそのような情報が含まれているかはわかりませんが、技術的な設計の観点(将来的に追加する機能としての可能性)から検討する価値はあるでしょう。v1 においては主要な関心事ではないと思いますが。

その仕組みは問題なさそうですが、なぜここで「groups」ではなく「roles」に切り替えたのか気になります。大きな問題ではありませんが、何か見落としているものがないか確認したいです。

UX の観点からは、「roles」と「groups」という用語が同時に使われることで混乱が生じる可能性があります。それが有用な技術的な区別に基づいているとしてもです。また、この背景知識を持たずに開発者がアクセスした場合、開発者側の混乱も考えられます。

個別のテーブルを設けるのは良いアイデアですが、provider_name ではなく user_associated_accounts と外部キーで関連付けるべきではないでしょうか。クリーンアップ処理などで役立つ可能性があります。この質問への答えは、製品観点からグループ/ロールの関連付けをどの程度関連アカウントと結びつけたいかにもよります。今から両者をリンクさせることにデメリットはありますか?

** 編集:すでに user_id 経由で関連付けられているようです。

それは問題なさそうですが、提案されたサイト設定によってプロバイダーごとにこの情報が保持されるため、ロールがまだ認識されていないケースもカバーできるのではないかと思っています。Discourse.authenticators を活用して、プロバイダーとそのクレームのメモリ内リストとして実装する方法があるかもしれません。

それは良い妥協案だと思います。特に、後述するサイト設定も併用する場合です。

プラグイン(つまり認証プロバイダー)単位で設定するのでしょうか?もしそうなら、賛成です。それであれば v1 の要件を満たせるでしょう。

ユーザーフローのまとめ、素晴らしいです :+1: 私が提案した比較的軽微な提案が反映されれば、この方向性に賛成です。

「いいね!」 1

:+1:

はい、その通りです。特に Google について考えていました。GSuite 組織では Google アカウントを使いたいという人が多く、そこには「グループ」の概念があるはずです。

「Identity Provider Groups」と「Discourse Groups」の混同を避けたかったのですが、名前を変えたことで逆に混乱を招いてしまった可能性もあります。「グループ」という呼称のままにするのも喜んで受け入れます。

非マネージド認証プロバイダーもまだサポートしているため、user_associated_account レコードが存在しない場合もあると考えました。ご指摘の通り、user_id を通じて結合することは可能ですね :+1:

サイト設定がここで役立つとは限りません。「ロール」を表す文字列の配列について話している場合、サイト設定はロールが具体的に何であるかを指定するのではなく、その配列を取得する方法を指定するだけになるからです。ご理解いただけますでしょうか?

素晴らしいですね :smiley:

「いいね!」 1

はい、その通りです。以前の実装をまだ考えていましたが、その時は設定自体に特定のグループを含めていました。ただ、今回はそうしていませんし、それで問題ありません。

これで PR の着手に必要な情報は十分だと思います。特に懸念点がなければ、今週後半に着手する予定です。何か進展があれば、ここで更新します。

素晴らしいですね!途中で何か問題やご質問がございましたら、喜んでお手伝いいたします :slight_smile:

「いいね!」 2

はい、ようやく作業中の成果物を共有できます。

いくつかの注記です。

初期の実装では、Google Apps HD グループのやや複雑なケースを選択しました。これは、プロバイダーからのドメイン固有のグループを考慮する必要性など、考えられる組み合わせを整理するのに役立つと思うからです。

このユースケースを実装するために、認証の時点で「二次認証(secondary authorization)」という新しい概念を導入し、段階的な認証を可能にしました。特定のユーザーのグループ権限(HD で認証している場合など)を要求する方法についていくつか検討しましたが、これが最も現実的だと判断しました。これは予想以上に大きな変更かもしれませんが、議論の価値はあると思います。

なお、Google HD グループのケースを実装するには、Google Apps HD グループの管理者以外のメンバーに、グループの一覧表示(管理者ディレクトリ API を通じて)を行うための委任管理者権限を付与する必要があります。これに役立つ「Groups Reader」という「ベータ」プレビルドの管理者ロールが実際に存在します。詳しくは Prebuilt administrator roles  |  User management  |  Google Workspace Help をご覧ください。

Google の実装は機能しています。設定後に HD で認証すると、Google HD グループが自動グループメンバーシップ設定で利用可能になり、その HD グループが選択されている場合は Discourse グループに自動的に追加されます。グループが削除された場合は削除されます(両方のアクションは詳細にログ記録されます)。また、その Google HD グループに所属する他のユーザーが認証すると、即座に追加されます。

詳細はコードと仕様から明らかでしょう。また、3 つの新しいテーブルを追加したことに気づかれると思います。より「軽量」なソリューションをいくつか試しましたが、ユーザーに関連するグループやグループに関連するグループの更新を処理する際に、それぞれがより複雑で非効率なものになってしまいました。各ケースで新しいテーブルを作成するしかないのは避けられないかもしれません。データモデリング全般について、アイデアがあれば歓迎します。


上記の概念的・製品に関する質問を除き、技術的な未完了タスクがいくつか残っています。この点についても提案を歓迎します。

  • 関連グループの label をシリアライズする(クライアント側でモデル化しない)。
  • 不足している仕様と QUnit テストを追加する。
  • 大量のデータが存在する場合に処理が遅くなる可能性があるため、user_associated_group / group_associated_group の作成・破棄をバックグラウンドジョブに移動する。
「いいね!」 3

これはとても素晴らしいですね!

「セカンダリ認証」の仕組みと、provider_domain カラムについては、少し慎重になる必要があります。なぜそれらが必要なのか、もう少し詳しく説明していただけますか?これらは Google 固有の要件のように思えます。最初の認証リクエストで admin.directory.group.readonly スコープを要求できないのでしょうか?あるいは、グループ名の先頭にドメインをプレフィックスする(あるいはドメインを完全に除外する、おそらくユーザーは単一の Google ホストドメインでのみこれを使用すると思われます)ことはできないでしょうか?

3 つのテーブルという構成には完全に賛成です。これで整理されます。

同意します :+1:

ここは注意が必要です。グループメンバーシップは、ユーザーが初めてサイトをロードするに割り当てられている必要があります。そうしないと、ユーザーは初めてログインした際にグループ固有の機能(例えば、セキュアなカテゴリなど)を見ることができません。したがって、user_associated_group レコードの変更は同期処理で処理すべきだと考えます。

一方、group_associated_group レコードの変更については、おっしゃる通りだと思います。ここでの変更は数千人のユーザーに影響を与える可能性があるため、in_batches で処理する必要があります。まずは同期処理で、UI にローディングスピナーを表示するところから始めるのがよいでしょう。これで、管理者は処理が実行中か完了したかを明確に確認できます。

もし処理時間が 30 秒(Unicorn のリクエストタイムアウト)に近づいてきた場合は、バックグラウンドジョブの導入を検討する必要があるかもしれません。

また、分散ミューテックス(DistributedMutex)によるロックの追加も検討する必要があるかもしれません。例えば、group_associated_group の変更が処理されている間にユーザーがログインした場合、どうなるでしょうか?全体のアーキテクチャが最終決定された後、GitHub でこのような話題について議論できればと思います。

興味深くフォローしています。関連する話題としてこちらを投げさせていただきます:Does `sso overrides groups` work with Oauth2?

私のユースケースでは、Discourse Connect の動作を他の認証プロバイダーでも実装されることに全く問題ありません。

「いいね!」 2

Great :slight_smile: 着実に進んでいます。

それぞれ順を追って対応します。

インクリメンタル認証(Incremental authorization)

最初のリクエストでグループ権限を要求できない理由は、誰がサインインしているのか、またユーザーが何を共有することに同意するのかがわからないからです。google_oauth2_hd 設定を使用して、Google 関連のグループマッピングをその設定を使用している人に制限することは可能ですが、これでは機能の範囲がかなり制限されてしまいます。Google Apps を使用するチームと、Google 認証も利用したい「一般」ユーザーが混在するケースは比較的よくあります。

*編集:補足します。グループスコープを要求した際、ユーザーがそれを付与できない場合(例:上記のように、HD が非管理者ユーザーに権限を委任していない場合など)、認証は失敗します。必須スコープ alongside オプションスコープを同時に要求することはできません。

さらに、このアプローチ、すなわち各種認証方法の実装において標準的な慣行として最初にグループスコープを要求するという方法は、代替案と比較してより Google 固有の性質が強くなる可能性があります。なぜなら、ログインを制限するためのホストドメインシステムに相当するものが常に存在するとは限らないからです。例えば、私の認識が間違っているかもしれませんが、Github OAuth2 ログインを特定の Github 組織に制限する方法はないと思います。

つまり、多くのケースでは、その認証方法を使用する全員に関連する groups スコープの付与を要求するか、機能自体を使用しないかという選択を迫られることになります。このアプローチは一部の文脈では機能するかもしれませんが、多くの場合は機能しません。このインクリメンタル認証のアプローチは、異なる認証方法に対して機能の実装により柔軟性を与えます。

Google が OAuth2 の分野でインクリメンタル認証を推進してきたことは事実です。例えば、この件に関する作業文書はすべて Google 従業員によって書かれています。

しかし、この概念は Google 固有のものではありません(他の人々は必ずしも「インクリメンタル認証」と呼んでいるわけではありません)。モバイルアプリのさまざまな形態で比較的一般的であり、他のプロバイダーも OAuth2 で採用し始めています。例えば、こちらが Facebook の同様のトピックに関するドキュメント です。

おそらくこの分野にはすでにご熟悉かと思いますが、「良い慣行」として以下の点が挙げられます。

  • 標準的な基本情報以上の権限を要求しようとしていることをユーザーに伝えること。
  • または、その理由を伝えること。

Discourse のログインフォームで「Facebook でサインアップ」をクリックしたユーザーが、メールアドレスに加えて Facebook グループへのアクセスも要求された場合、離脱してしまう可能性があります。Facebook は以下のように述べています。

一般的なルールとして、アプリが要求する権限が多ければ多いほど、ユーザーが Facebook を使ってアプリにログインする可能性は低くなります。実際、私たちの調査によると、4 つ以上の権限を要求するアプリは、完了したログイン数に大幅な離脱が見られます。

これは、認証の時点で追加のスコープを要求することが本当に良いアイデアなのかという疑問を投げかけます。基本的に、他に良い選択肢がないと結論付けました。いくつかのシナリオではグループへの即時アクセスが必要であること(あなたが示唆した通り)と、最初から要求されなければ多くのユーザーがプロフィールやグループページなどでグループの認証のために追加のステップを踏まないという現実があります。

これは認証の時点で実施する必要があるため、前述の問題、すなわち私が「二次認証(secondary authorization)」システムを実装した理由に戻ってきます。これは確かに軽量な「システム」を意図したものであり、他のサービス(例えば Facebook や Github)が、ユーザーが認証した後(およびオプションで基本情報に関する特定のテストを通過した後)にユーザーのグループへのアクセスを取得するために、二次認証リクエストを実装することが比較的容易です。

各プロバイダーは以下のことを行う必要があります。

  • secondary_authorization_url を含む結果を返す

  • state パラメータを使用して、ユーザーがどの認証リクエストの段階にいるかを検出する

  • users/omniauth_callbacks/secondary_authorization.html.erb 用の omniauth_secondary_authorization_description を提供する。例えば、Google の場合は以下です(ユーザーが二次認証のリダイレクトを確認する前に表示されるメッセージ)。

    %{domain} のメールでサインインされたため、%{domain} のグループを表示する許可をお伺いする必要があります。

これらの要素のいずれも Google 固有のものではありません。

ここで私がやりたいのは、ユーザーが二次リクエストに対して「いいえ」と回答しても、認証を継続できるようにすることです。Google Apps HD のシナリオでは、アカウントがホストドメインの一部である場合、ユーザーは「いいえ」と言うことを望まない、あるいは立場上不可能であることが多いため、これは実際には問題になりません。しかし、ここでの認証シナリオの全範囲を考慮に入れるために、これを考慮に入れるべきだと考えます。

最後に、associated_groups が機能するために二次認証が必須ではないことも付記します。認証プロバイダーは最初にグループスコープを要求し、最初のレスポンスを受信した後にグループを認証結果に追加するだけでよいのです。実際、基本的な oauth2 および openid connect プラグインにそのオプションを組み込むべきでしょう。

プロバイダードメイン(Provider Domain)

associated_groups テーブルには、サイト管理者が読み取れる二次識別子の何らかの形態が必要だと考えます。グループ名だけでは不十分なシナリオがいくつかあります。各サービスの同等の概念間で名前が衝突する可能性があります。

  1. 多ドメイン Google グループ管理(1 つのワークスペースに複数のドメインを持つことも可能です)
  2. 多組織 Github グループ管理
  3. 多サーバー Discord ロール管理
    など

domainnamespace に変更するかもしれません。グループの name に含めることもできますが、それがどのような利点をもたらすでしょうか?将来的に「ドメイン」や「ネームスペース」でクエリを実行する必要があるかもしれません。はい、おそらく namespace の方が domain よりも適しているでしょう。

これが「管理者が読み取れる」必要がある理由は、それがグループ UI で管理者に表示されるラベルに使用され、一部は曖昧さ解消の目的のためだからです。

もし存在する場合、provider_id もここに格納しようとするのが妥当かどうか検討しています。将来的には役立つかもしれません。

はい、これらすべてに同意しますし、アドバイスもありがとうございます。この部分は試してみますので、PR でさらに議論しましょう。

「いいね!」 4

@david この件についていくつか更新をプッシュしました。

  • group_associated_group における DistributedMutxesin_batches
  • 受入テスト(すでに rspec はありました)

さらに作業が必要なのは間違いありませんが、現時点では仕様に沿って動作しており、すべてのテストが通過しています。実際に試してみてください。ご意見や希望の変更点をお知らせください。

「いいね!」 5

とりあえず非ドラフトとしてマークするのはどうでしょうか?

「いいね!」 1

@angus さん、こんにちは!この件についてさらに進展がありましたでしょうか?私は単純な「strict」動作に非常に興味を持っています。OAuth2/OpenID Connect プロバイダーは私たちが制御しているため、「二次的な承認」ケースについては心配していません。そのような機能がもう少し早く実装される可能性はありますか?

参考までに、私たちの環境はここでドキュメント化されています:Infrastructure/Authentication - Fedora Project Wiki
また、Discourse に対して OAuth2 スコープ openid profile email https://id.fedoraproject.org/scope/groups を要求するように設定しました。

基本的には、以下のことだけを望んでいます:

  • 信頼レベルとスタッフグループは変更しない
  • SSO から提供されたグループリストに既に存在する Discourse グループに、ユーザーがまだ所属していなければ追加する
  • リストに含まれていないグループからユーザーを除外する

正直に言うと、すべての複雑さを理解しているわけではありません。私が理解していない複雑な点があるのでしょうか?

「いいね!」 2

Matt、今週末はこの件に取り組む時間を確保しました。来週、おそらく GitHub の PR にて更新をお知らせします。

「いいね!」 2

素晴らしい、どうもありがとうございます。しつこく聞こえるかもしれませんが、Discourse サポートでは、このトピックに投稿することが現在の状況を確認する最善の方法だと提案されました。:slight_smile:

Fedora の Discourse サイトで、これがあれば今ではできないことがたくさんできるようになるため、皆さんのこの取り組みを心待ちにしています!

「いいね!」 2