Discourse OAuth2 基本

:discourse2: Summary Discourse OAuth2 Basic supports basic OAuth2 providers, assuming they have a JSON API endpoint where user details can be retrieved by token.
:open_book: Install Guide This plugin is bundled with Discourse core. There is no need to install the plugin separately.

Features

This plugin allows you to use a basic OAuth2 provider as authentication for Discourse. It should work with many providers, with the caveat that they must provide a JSON endpoint for retrieving information about the user you are logging in.

This is mainly useful for people who are using login providers that aren’t very popular. If you want to use Google, Facebook or Twitter, those are included out of the box and you don’t need this plugin. You can also look for other login providers in our Github Repo.

Configuration

Basic Configuration

  1. First, register your Discourse application with your OAuth2 provider. It will require a Redirect URI which will be:

    http://DISCOURSE_HOST/auth/oauth2_basic/callback

:information_source: Replace DISCOURSE_HOST with the appropriate value, and make sure you are using https if enabled. The OAuth2 provider should supply you with a client ID and secret, as well as a couple of URLs.

  1. Visit your AdminSettingsOAuth2 Login and fill in the basic configuration for the OAuth2 provider:
  • oauth2_enabled - check this off to enable the feature
  • oauth2_client_id - the client ID from your provider
  • oauth2_client_secret - the client secret from your provider
  • oauth2_authorize_url - your provider’s authorization URL
  • oauth2_token_url - your provider’s token URL.

:information_source: If you can’t figure out the values for the above settings, check the developer documentation from your provider or contact their customer support.

Configuring the JSON User Endpoint

Discourse is now capable of receiving an authorization token from your OAuth2 provider. Unfortunately, Discourse requires more information to be able to complete the authentication.

We require an API endpoint that can be contacted to retrieve information about the user based on the token.

For example, the OAuth2 provider SoundCloud provides such a URL. If you have an OAuth2 token for SoundCloud, you can make a GET request to https://api.soundcloud.com/me?oauth_token=A_VALID_TOKEN and will get back a JSON object containing information on the user.

To configure this on Discourse, we need to set the value of the oauth2_user_json_url setting. In this case, we’ll input the value of:

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

The part with :token tells Discourse that it needs to replace that value with the authorization token it received when the authentication completed.

There is one last step to complete. We need to tell Discourse what attributes are available in the JSON it received. Here’s a sample response from 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"
}

The oauth2_json_user_id_path, oauth2_json_username_path, oauth2_json_name_path and oauth2_json_email_path variables should be set to point to the appropriate attributes in the JSON.

The only mandatory attribute is id - we need that so when the user logs on in the future that we can pull up the correct account. The others are great if available – they will make the signup process faster for the user as they will be pre-populated in the form.

Here’s how I configured the JSON path settings:

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

I used permalink because it seems more similar to what Discourse expects for a username than the username in their JSON. Notice I omitted the email path: SoundCloud do not provide an email so the user will have to provide and verify this when they sign up the first time on Discourse.

If the properties you want from your JSON object are nested, you can use periods. So for example if the API returned a different structure like this:

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

You could use user.id for the oauth2_json_user_id_path and user.email.address for oauth2_json_email_path.

If the key itself includes periods, you will need to put double quotes around it, or escape the periods with a backslash. For example, given this JSON:

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

You would specify the path as example\.com/uid or "example.com/uid"

:warning: If you set oauth2_json_email_path, the OAuth2 provider must confirm the user owns that email address. Failure to do this can result in account takeover in Discourse!

:discourse2: Hosted by us? This plugin is available on our Business and Enterprise plans. OAuth 2.0 & OpenID Connect Support | Discourse - Civilized Discussion

Last edited by @tobiaseigen 2025-07-16T21:39:12Z

Check documentPerform check on document:
「いいね!」 28

こんにちは。
アプリケーションで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エラーを生成するのでしょうか?