Discourse OAuth2 基本

:discourse2: 概要 Discourse OAuth2 Basic は、ユーザー詳細をトークンで取得できる JSON API エンドポイントを持つ基本的な OAuth2 プロバイダーをサポートします。
:open_book: インストールガイド このプラグインは Discourse コアにバンドルされています。プラグインを個別にインストールする必要はありません。

機能

このプラグインを使用すると、基本的な OAuth2 プロバイダーを Discourse の認証として利用できます。多くのプロバイダーで動作しますが、ログインしているユーザーに関する情報を取得するための JSON エンドポイントを提供しなければならないという注意点があります。

これは主に、あまり普及していないログインプロバイダーを使用している人々にとって役立ちます。Google、Facebook、Twitter を使用したい場合は、それらは最初から含まれているため、このプラグインは不要です。また、Github リポジトリ で他のログインプロバイダーを探すこともできます。

設定

基本設定

  1. まず、OAuth2 プロバイダーで Discourse アプリケーションを登録します。リダイレクト URI が必要になります。それは以下のようになります:

    http://DISCOURSE_HOST/auth/oauth2_basic/callback

:information_source: DISCOURSE_HOST を適切な値に置き換え、有効な場合は https を使用していることを確認してください。OAuth2 プロバイダーは client IDsecret、そしていくつかの URL を提供します。

  1. 管理設定OAuth2 ログイン に移動し、OAuth2 プロバイダーの基本設定を入力します:
  • oauth2_enabled - この機能を有効にするためにチェックを入れてください
  • oauth2_client_id - プロバイダーからのクライアント ID
  • oauth2_client_secret - プロバイダーからのクライアントシークレット
  • oauth2_authorize_url - プロバイダーの認証 URL
  • oauth2_token_url - プロバイダーのトークン URL

:information_source: 上記の設定値がわからない場合は、プロバイダーの開発者ドキュメントを確認するか、カスタマーサポートに連絡してください。

JSON ユーザーエンドポイントの設定

Discourse は、OAuth2 プロバイダーから認証トークンを受け取ることができるようになりました。残念ながら、認証を完了するためには、Discourse はさらに多くの情報を必要とします。

トークンに基づいてユーザー情報を取得できる API エンドポイントが必要です。

例えば、OAuth2 プロバイダーの SoundCloud はそのような URL を提供しています。SoundCloud の OAuth2 トークンを持っている場合、https://api.soundcloud.com/me?oauth_token=A_VALID_TOKEN に対して GET リクエストを送信すると、ユーザー情報を含む JSON オブジェクトが返されます。

Discourse でこれを設定するには、oauth2_user_json_url 設定の値を設定する必要があります。この場合、以下の値を入力します:

https://api.soundcloud.com/me?oauth_token=:token

:token の部分は、Discourse が認証完了時に受け取った認証トークンでその値を置き換える必要があることを示しています。

最後のステップがあります。Discourse に受け取った JSON で利用可能な属性を伝える必要があります。以下は SoundCloud からのサンプル応答です:

{
  "id": 3207,
  "permalink": "jwagener",
  "username": "Johannes Wagener",
  "uri": "https://api.soundcloud.com/users/3207",
  "permalink_url": "http://soundcloud.com/jwagener",
  "avatar_url": "http://i1.sndcdn.com/avatars-000001552142-pbw8yd-large.jpg?142a848",
  "country": "Germany",
  "full_name": "Johannes Wagener",
  "city": "Berlin"
}

oauth2_json_user_id_pathoauth2_json_username_pathoauth2_json_name_pathoauth2_json_email_path 変数を、JSON の適切な属性を指すように設定する必要があります。

必須の属性は id のみです。将来ユーザーがログインしたときに正しいアカウントを取得するために必要です。他の属性も利用可能であれば素晴らしいです。これらはユーザーのサインアッププロセスを高速化し、フォームに事前に記入されます。

以下は、JSON パス設定を構成した方法です:

  oauth2_json_user_id_path: 'id'
  oauth2_json_username_path: 'permalink'
  oauth2_json_name_path: 'full_name'

permalink を使用したのは、Discourse がユーザー名として期待するものの方が、JSON 内のユーザー名よりも似ているように思えたためです。メールアドレスのパスは省略しました。SoundCloud はメールアドレスを提供していないため、ユーザーは初めて Discourse にサインアップする際に自分で提供して確認する必要があります。

JSON オブジェクトから取得したいプロパティがネストされている場合は、ピリオドを使用できます。例えば、API が以下のような異なる構造を返した場合:

{
  "user": {
    "id": 1234,
    "email": {
      "address": "test@example.com"
    }
  }
}

oauth2_json_user_id_path には user.id を、oauth2_json_email_path には user.email.address を使用できます。

キー自体にピリオドが含まれている場合は、二重引用符で囲むか、バックスラッシュでピリオドをエスケープする必要があります。例えば、以下の JSON が与えられた場合:

{
  "example.com/uid": "myuid"
}

パスは example\.com/uid または "example.com/uid" として指定します。

:warning: oauth2_json_email_path を設定した場合、OAuth2 プロバイダーはユーザーがそのメールアドレスを所有していることを確認する必要があります。 これを怠ると、Discourse でのアカウント乗っ取りにつながる可能性があります!

:discourse2: 当社でホストされていますか?このプラグインは、Business および Enterprise プランで利用可能です。OAuth 2.0 & OpenID Connect Support | Discourse - Civilized Discussion

:spiral_notepad: ユーザーのサインアップを自動化する必要がありますか?Auto-provisioning user accounts when SSO is enabled を参照してください。

「いいね!」 28
Keycloak with Discourse
Discourse SSO with OAuth2
Login from another user database
Shopify Integration
How can we enable Auth0 SSO in Discourse
OAuth2 integration with Drupal
OAuth connection of discourse
Login flow (Flask -> Discourse -> Flask) with OAuth
How to use Oauth2 service provided by discourse?
How to login to discourse from external website
Is "partial" SSO possible?
Set up Salesforce auth using OAuth2 basic support plugin
How to force users link phone number when they using Discourse?
OAuth2 Custom Redirects Plugin
Custom Login / Registration from another API
Login on discourse using mastodon credentials
Open source will support customized provider SSO
Oauth2 with fusionauth cert issues
Migrate a Jive Clearspace forum to Discourse
Configure sign up and log in with Auth0 using the OAuth2 Basic Plugin
Error during SSO integration - Wholistic Minds
What is supposed to go in “DISCOURSE_HOST”?
Custom Provider log-in with OAuth only sign-up/log-in
Discord, Google and Microsoft login, is oAuth2 enough?
Populating email field on login page
CodeBerg support
Gate our community to just members of our Shopify site?
Intergrate Discourse with keycloak
Integration into custom auth system where emails are not unique?
Twitter login doesn't work on meta
Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso)
Question about Docker Manager?
Discourse OpenID Connect (OIDC)
🧩 How to Build an Android App User Community with Discourse? [HeyApks Project]
Bundling more popular plugins with Discourse core
Drupal 8 and Discourse shared SSO
Discourse for self hosting
Discourse + Intercom (Current User Id)
Auto-provisioning user accounts when SSO is enabled
ADFS Authentication
Pulling user auth0 sub from OAuth2.0 plugin
Suggestion for improving Integrated Authentication development
Github and Twitter Login/Sign-Up Functionality?
Automatically creating a user when logging in with Webflow/Memberspace
Switching out authentication for a passwordless alternative
Removing Yahoo login from Core, and deprecating OpenID 2.0
Shopify Integration
SSO with TownNews CMS
SSO and Auth0

こんにちは。
アプリケーションでOAuth2 Basicを使用してDiscourseとの統合を試みていますが、ログで以下のエラーが発生しています。
注:接続のデバッグのためにNGROKを使用しています。

OAuth2 Debugging: request POST https://formshare.ngrok.io/oauth2/token

Headers: {"User-Agent"=>"Faraday v1.9.3", "Content-Type"=>"application/x-www-form-urlencoded", "Authorization"=>"Basic S2k2SFZtTVpuSTFHUExiRXVlWVJDNENiOkNvb1k0anlQemt3dWNRV21Sa2FWOVNnbHZLbjJFT3cxc3BIMmtMck9yY21vNDM4Tg=="}

Body: {"client_id"=>"Ki6HVmMZnI1GPLbEueYRC4Cb", "client_secret"=>"...some_secret_...", "grant_type"=>"authorization_code", "code"=>"5pPCrsp0pZ84373MNaHh2cuskfc8AlbfmdwMBFIVW4n4z9aX", :redirect_uri=>"https://community.formshare.org/auth/oauth2_basic/callback"}

------------------

OAuth2 Debugging: response status 200

From POST https://formshare.ngrok.io/oauth2/token

Headers: {"content-length"=>"108", "content-type"=>"text/html; charset=UTF-8", "date"=>"Thu, 01 Sep 2022 21:42:08 GMT", "ngrok-trace-id"=>"79cdc3f1c3eae5e37a30796aebbf9bd6", "server"=>"gunicorn"}

Body: {"token_type": "Bearer", "access_token": "p0FVuwjSXL1ZINEklMAVqUlpZxSll1SgnbpE8YWP4C", "expires_in": 864000}

-----------------------------------

(oauth2_basic) Authentication failure! invalid_credentials: OAuth2::Error, {"token_type": "Bearer", "access_token": "p0FVuwjSXL1ZINEklMAVqUlpZxSll1SgnbpE8YWP4C", "expires_in": 864000}

「oauth2 callback user id path」と「oauth2 callback user info paths」のパラメータは空のままにしました。

何かアイデアがあれば教えてください。

MicrosoftのXBLサービスとの認証にこれを使用できますか?

ロジックはこれと同様であると推測しますか?

皆さん、こんにちは。このプラグインを、社内のOauth2サーバーと、認可コードフローで設定しようとしています。

ユーザーが「Oauthで接続」をクリックすると、/authorize エンドポイントは機能し、コールバックにコードが返されます。しかし、その後Discourseは「おっと。このディスカッションフォーラムを動かしているソフトウェアで予期しない問題が発生しました」という一般的な500エラーを表示し、/token エンドポイントにはアクセスされません。

エラーログは以下の通りです。
OAuth2::ConnectionError (FinalDestination: すべて解決されたIPが無効でした) lib/final_destination/ssrf_detector.rb:74:in lookup_and_filter_ips' lib/final_destination/http.rb:13:in connect’ lib/midd

ホスト名 discourse-app
プロセスID 653
アプリケーションバージョン 702f27e6ee10ac257f5fee3f331d05f5fa5d7a45
HTTP_HOST *****
REQUEST_METHOD GET
HTTP_USER_AGENT Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
HTTP_REFERER *****
HTTP_X_FORWARDED_FOR *****
HTTP_X_REAL_IP *****
時間 午後10時25分
パラメータ
コード def50200babf84f7376f99fefa34369d876566b6bc0a341d8fba431999a72549ac06f6aad01df6fa43061707c525ba5d725ad
状態 20139e0a134a5972566d4ddb9e5216973a

私の理解では、IPアドレスに問題があるということでしょうか?現在、Oauth2サーバーは私の開発環境(localhost)でホストされており、認可およびトークンエンドポイントはそれに応じて設定されています。これは問題でしょうか?

問題が見つかりました。

  1. 何らかの理由で /token エンドポイントが呼び出されていませんでした。OAuth に関連する管理者パラメータのオプションを最大まで設定した後、エンドポイントは応答なしで呼び出されました。
  2. /token エンドポイントを呼び出すのは webclient ではなく Discourse サーバーであることを忘れっていました。そのため、サーバーは私のローカルホスト OAuth2 サーバーに到達できませんでした。OAuth2 サーバーをドメインの後ろに置いたことで問題は解決しました。

これで既存のユーザーは接続できますが、このプラグインを通じて新しいユーザーにサインインさせる方法がわかりません。
ユーザーが OAuth でサインインすると、Discourse サーバーにアクティブなアカウントがないというエラーが表示されます。これは新しいユーザーなので当然です。

ログインではなく、ユーザーにサインインさせるための専用のコールバックはありますか?または、アカウント作成を許可するための特定のパラメータを設定する必要がありますか?

私の会社の OAuth サーバーでは、あるフィールドにわずかなタイプミスがあり、/profile JSON レスポンスが生成されていました。タイプミスを修正した後はすべて問題ありませんでした。
しかし、Discourse のログは非常に誤解を招く可能性があると言わざるを得ません!コールバックには何も問題はありませんでした。

こんにちはチーム、

ユーザーのJSONリクエストに必要なIDを認証レスポンスから取得する際に問題が発生しています。ドキュメントを読むと、アカウントIDはネストされた配列で送信されているようです。

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
   "access_token":"2YotnFZFEjr1zCsicMWpAA",
   "token_type":"Bearer",
   "expires_in":1800,
   "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
   "permissions":[
      {
        "accountId":123,
        "availableScopes":["contacts_view", "contacts_me",
"contacts_edit", "finances_view", "events_view"]
      }
   ]
}

oauth2コールバックのユーザーIDパスを permissions[0].accountId に設定しようとしましたが、uidの値は常に空白です。残念ながら、ユーザーJSONを取得する呼び出しでは、JSON URLにこのaccountIdが必要です。

パーミッションを渡すことで、これを機能させることができました。permissions.first.accountId を渡したところ、テストプロパティにパーミッションを渡すと、配列は既にRubyの配列として解析されていました。残念ながら、フィールドは配列要素を呼び出すためのRuby構文を拒否し、JavaScript構文を使用しようとすると TypeError String to Integer が発生しました。幸いにもRubyには上記の構文がありましたが、これが意図された方法でしょうか?

Authentik OAuth2 でこれを機能させることができましたが、oauth2 user json url 設定でいくつかの問題が発生しました。Authentik の user_info エンドポイント (/application/o/userinfo/) を使用しましたが、フィールドのマッピング方法がわかりませんでした。Authentik の OAuth2 で Discourse をセットアップする方法を探している人のために、概要は次のとおりです。

  • User id path: preferred_username
  • Username path: preferred_username
  • Name path: name
  • Email path: email
  • Email verified path: email_verified
  • Avatar: 空

以下の問題がありました。

  1. 最初、JSON URL https://DOMAIN/application/o/userinfo/ の末尾のスラッシュを忘れていました。これにより、ユーザー情報リクエスト (ソースへのパーマリンク) が 301 HTTP コードを返し、ログインが失敗しました。末尾のスラッシュが仕様で必要かどうかはわかりませんが、301 を正しく処理できると良いかもしれません。
  2. これのデバッグはトリッキーであることが判明しました。oauth2 debug auth 設定は非常に役立ちましたが… Logster は、意味のある応答データを実際にダンプする前にデバッグログを切り捨てます。コンテナ内のログ行を次のように手動で変更する必要がありました。
    log("user_json_response: #{user_json_response.status} #{user_json_response.headers} #{user_json_response.body}")
    
    このログ行は更新される可能性がありますか?これにより、他の人が JSON 属性パスを理解するのに役立つと思います。
「いいね!」 4

Auth0をプラグインでセットアップしましたが、アバターが取得されません。

関連する設定は以下の通りです。

  DISCOURSE_OAUTH2_ENABLED: true
  DISCOURSE_OAUTH2_CLIENT_ID: '${DISCOURSE_OAUTH2_CLIENT_ID}'
  DISCOURSE_OAUTH2_CLIENT_SECRET: '${DISCOURSE_OAUTH2_CLIENT_SECRET}'
  DISCOURSE_OAUTH2_AUTHORIZE_URL: '${DISCOURSE_OAUTH2_ISSUER}/authorize?connection=xxx&login_options=yyy'
  DISCOURSE_OAUTH2_TOKEN_URL: '${DISCOURSE_OAUTH2_ISSUER}/oauth/token'
  DISCOURSE_OAUTH2_USER_JSON_URL: '${DISCOURSE_OAUTH2_ISSUER}/userinfo'
  DISCOURSE_OAUTH2_SCOPE: 'email openid profile'
  DISCOURSE_OAUTH2_JSON_USER_ID_PATH: 'sub'
  DISCOURSE_OAUTH2_JSON_USERNAME_PATH: 'nickname'
  DISCOURSE_OAUTH2_JSON_NAME_PATH: 'name'
  DISCOURSE_OAUTH2_JSON_EMAIL_PATH: 'email'
  DISCOURSE_OAUTH2_JSON_EMAIL_VERIFIED_PATH: 'email_verified'
  DISCOURSE_OAUTH2_JSON_AVATAR_PATH: 'picture'
  DISCOURSE_OAUTH2_EMAIL_VERIFIED: true
  DISCOURSE_OAUTH2_OVERRIDES_EMAIL: true
  DISCOURSE_OAUTH2_ALLOW_ASSOCIATION_CHANGE: false

デバッグログでは、JSONレスポンスにpicture要素が設定されていることがわかりますが、新規ユーザーでも既存ユーザーでも、ユーザーのアバターは変更されません。

何を見落としていますか?

ログインボタンのアイコンを別のアイコンまたは画像に置き換える最善の方法は何ですか?

.btn-social.oauth2_basic:before {
    content: url('https://www.contoso.com/path/to/image');
}

.btn-social.oauth2_basic > svg {
    display: none;
}

これで十分ですが、少しハッキーな感じがします。

「いいね!」 2

プラグインは、ユーザーの初回作成時にのみアバター/ユーザー名を更新し、ログイン時には更新されないようです。

これを修正して、ログイン/再接続時にもプラグインがアバターを更新するようにする方法はありますか?

auth overrides emailauth overrides usernameauth overrides name の設定を使用して、それらを将来のログインに適用できます。残念ながら、アバターに同様の設定はありませんが、pr-welcome です。

「いいね!」 2

ありがとうございます!後でこれらを見つけました。リポジトリをフォークして、Robloxで機能するように独自のバージョンを追加しました。これにはアバターのオーバーライドも含まれていました。これはDiscourseConnectのアバターオーバーライドを使用しているだけで、人々はそれを変更できないと信じています。

ただ、RobloxはOAuthでメールを提供していないので、残念ながらメールでサインアップしてもらう必要があります。しかし、それは皆さんにとっては問題ではありませんね(笑)。

投稿が新しいトピックに分割されました:Twitterログインがメタで機能しない

これはまだ機能するかどうか、誰か知っていますか?

はい。このプラグインは動作すると確信しています。:+1:

「いいね!」 1

こんにちは。このプラグインを discourse discuss.frontendlead.com に統合できました。Teachable OAuth を使用しています: https://docs.teachable.com/docs/oauth-quickstart-guide

ただし、Teachable で現在有料アカウントを持っている場合にのみ、正常に登録できるようにしたいと考えています。この処理を行うには、プラグインにカスタム機能を追加する必要があるかと思います。設定に、OAuth 後に開発者が特定の操作を実行できるカスタムコードという別のフィールドを導入することは可能でしょうか?あるいは、他に良い提案があれば教えてください。

編集: リポジトリをフォークして、ここで動作させることができました:

Teachable を使用していて同様のことを試みている他の人がいれば、私のリポジトリはそのまま動作します。唯一の違いは、コースを購入していない場合、私のドメインにアクセスして購入する必要があるというメッセージが表示されることです。これは、ご自身のユースケースに合わせて更新する必要があるかもしれません。

「いいね!」 2

それは素晴らしいですね!

Discourse PatreonプラグインのOAuth2登録にも同様の状況があります。「Patreonでログイン」が有効になっている場合、Patreonアカウントを持つ誰もがDiscourseサイトに登録できます。サイト所有者が一般的に望むのは、_自分の_サポーターのみがDiscourseアカウントを登録できるようにすることです。Patreon認証に同様のロジックを追加できるように、Patreonから詳細情報が返されるのでしょうか?

「いいね!」 1

@qlands さんと同じエラーが発生しています。

当初は、プロファイル情報をトークンに含めて送信する予定でした。それが機能しなかったので、JSONアプローチを試すためにインデントを削除しましたが、JSONファイルを呼び出すところまで到達しません。

エラーメッセージは次のとおりです。

(oauth2_basic) 認証失敗! invalid_credentials: OAuth2::Error, {
  "access_token":"fa79b6fe0763862f5a8fd8",
  "token_type":"Bearer",
  "expires_in":3600,
  "scope":"profile"
}

上記の返信で何か問題が見られますか?
OAuth2サーバーがトークンを200で返したのに、なぜプラグインがinvalid_credentialsエラーを生成するのでしょうか?