OAUTH2 基本が最悪すぎる :-(

皆さん、

OAUTH2 を 2 日間設定しようとしていますが、問題が発生しています。

ドキュメントに従ってすべてを設定しましたが、常に次のエラーが発生します。

(oauth2_basic) Authentication failure! invalid_scope: OmniAuth::Strategies::OAuth2::CallbackError, invalid_scope | Unknown/invalid scope(s)
Started GET "/auth/failure?message=invalid_scope&origin=<censored>%2Latest&strategy=oauth2_basic" for 10.153.107.106 at 2024-11-27 05:30:33 +0000
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"message"=>"invalid_scope", "origin"=>"<censored>/latest", "strategy"=>"oauth2_basic"}

私のボードの設定(スコープに関するもの)は次のとおりです。

IdP は次のように設定されています。

これをさらにデバッグする方法について、何かヒントはありますか?

テストできるクールなカール、またはより良いデバッグ出力(すでにリッチデバッグオプションをオンにしています)はありますか?

これに狂いそうです :frowning:

よろしくお願いします!

WS

UPDATE:

オプションを「scope」だけにリセットしました。

しかし、うまくいきませんでした :frowning:

「いいね!」 2

IdP の UI でスコープが間違っていたことに気づきました…

openId が UI にあり、openid が正しいものです :slight_smile:

さらに一歩進みましたが、タイムアウトが発生しています

image

この呼び出しの後


OAuth2 デバッグ: リクエスト POST https://<myAuthProvider/auth/oauth2/realms/root/realms/<realm>/access_token

ヘッダー:
--- !ruby/hash-with-ivars:Faraday::Utils::Headers
ivars:
  :@names:
    user-agent: User-Agent
    content-type: Content-Type
elements:
  User-Agent: Faraday v2.12.1
  Content-Type: application/x-www-form-urlencoded


本文:
---
client_id: <client-id>
client_secret: <client-secret>
grant_type: authorization_code
code: <code
redirect_uri: https://<myDiscourse>/auth/oauth2_basic/callback

そして

しかし、コードを取得した承認呼び出しは正常に完了したため、ネットワークの問題ではないはずですよね?

「いいね!」 1

curlで呼び出しを実行すると、以下のようになります。

curl --request POST \
  --url https://<IdP address>/auth/oauth2/realms/root/realms/<realm>/access_token \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data client_id=<clientId> \
  --data client_secret=<secret> \
  --data grant_type=authorization_code \
  --data code=<code > \
  --data redirect_uri=https://<discourse>/auth/oauth2_basic/callback

discourse Dockerコンテナ内から実行すると、次のようになります。

{
  "access_token": "<token>",
  "refresh_token": "<refresh_token>",
  "scope": "openid profile email",
  "id_token": "<censored>",
  "token_type": "Bearer",
  "expires_in": 7199
}

これが原因である可能性がありますか?

image

これらのフィールドが応答に含まれていません :frowning:

「いいね!」 2

誰もいませんか? :frowning:

「いいね!」 1

近所のための最初のディスコースページと、徐々に子供たちの学校へと移行していくのに必要な労力についてリサーチしているので、このトピックに非常に興味があります。様々なプラットフォームからの通知に圧倒されています。

ページへのアクセスを容易にすることが重要なので、いくつかお手伝いしたいと思います。私はRubyの初心者なので、見つけたリソースとそれらに関するアイデアしか提供できません。

すでに確認済みかもしれませんが、Discourse OpenID ConnectのGitHubリポジトリを確認することをお勧めします。

このリポジトリには37人の貢献者がおり、そのうちの1人があなたの質問に答えるのに役立つだろうと想像します。

これは素晴らしい質問なので、お役に立てば幸いです。

「いいね!」 1

@thecatfix さん、

有望そうですね。すぐに試して、できるだけ早くフィードバックします。
残念ながら、今日は時間がありません。週末に作業できるかもしれません。

ありがとうございます。良い週末をお過ごしください!

こんにちは。

待ちきれずに本日テストしましたが、当社の EAM 部門の担当者がこの検出を誤って設定したようです。機能せず、認証に失敗した無効なクライアントというエラーが表示されます。ただし、curl でテストしたところ、認証情報は 1000% 確実に機能しています。
そのため、最初に戻りました。

興味深いのは、常に認証エンドポイントへのリクエストでタイムアウトエラーが発生しており、それが非常に速く発生することです。

Faraday::TimeoutError (Net::ReadTimeout with #<TCPSocket:(closed)>)

これを見つけましたが、Discourse でも同様のことが可能かどうか興味があります。

私はまったく Ruby の人間ではないので、助けが必要です。

Discourse 側で処理されるすべてのリクエストをデバッグしたいと考えています。それは可能ですか?
ローカルプロキシをインストールして呼び出しをインターセプトすることも考えましたが、これに着手する前に、もっと簡単な方法がないかお尋ねしたかったのです :slight_smile:

生のHTTPトラフィックを表示したいですか、それともコードにジャンプできるようにしたいですか?

生のトラフィック…

ヘッダーとペイロードが送信されるリクエスト…

それは可能ですか?

コンテナ内から行うのが最も簡単な方法です。コンテナに入り、以下を実行することで、nginxとDiscourse間のリクエストを傍受して表示できます。

apt-get update && apt-get -y install scapy
scapy

# scapyプロンプトで、以下を貼り付けます:
class Callback:
  def __init__(self):
    self.last = None
  def prn(self, p):
    if p != self.last: # loでキャプチャすると2回キャプチャされる
      self.last = p
      p.hide_defaults()
      print(repr(p)) # この行はパケットを表示します。残すか削除するかは任意です
      if scapy.packet.Raw in p.layers():
        try:
          print(p.load.decode())
        except:
          print(p.load)

sniff(filter="port 3000", iface="lo", prn=Callback().prn)
「いいね!」 1

これはすごいですね、ありがとうございます…まさにこのようなツールを探していました!

うーん…しかし

ディスコースはコールバックを受け取って、その後…
私の理解では、ユーザー情報を取得したコードでユーザー情報エンドポイントに連絡するはずですが、HTTP 500エラーが出ています。


GET /auth/oauth2_basic/callback?code=_B1HRB1e6kZKc8nuGLkzGC8&iss=https%3A%2F%2F%3CmyAuthDomain%3E%3A443%2Fauth%2Foauth2%2Frealms%2Froot%2Frealms%2Fintranetrealm&state=544801ae7e8262ea1667ea7531487f28e83aae232d5182b4&client_id=eadaa55a-1697-494a-8fg5-bb1137c68caa HTTP/1.0
Host: <discourseHost>
X-Request-Start: t=1732956951.485
X-Real-IP: 10.111.101.84
X-Forwarded-For: 10.131.101.84
X-Forwarded-Proto: https
Connection: close
cache-control: max-age=0
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
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.7
sec-fetch-site: same-site
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
sec-ch-ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
referer: https://discourseHost/
accept-encoding: gzip, deflate, br, zstd
accept-language: de-DE,de;q=0.9
priority: u=0, i
cookie: lbwdn=01; win=teUNUPSc8oibB......

<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=52 id=7742 flags=DF frag=0 ttl=127 proto=tcp chksum=0xdf83  src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=3000 dport=33574 seq=271589520 ack=3955524768 dataofs=8 flags=A window=499 chksum=0xfe28 options=[('NOP', None), ('NOP', None), ('Timestamp', (3962821542, 3962821542))] |>>>
<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=281 id=55898 flags=DF frag=0 ttl=127 proto=tcp chksum=0x2282  src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=3000 dport=33530 seq=491394 ack=1852886175 dataofs=8 flags=PA window=507 chksum=0xff0d options=[('NOP', None), ('NOP', None), ('Timestamp', (3962823893, 3962816870))] |>>>
<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=52 id=15439 flags=DF frag=0 ttl=127 proto=tcp chksum=0xc172  src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=33574 dport=3000 seq=3955524768 ack=271589749 dataofs=8 flags=A window=511 chksum=0xfe28 options=[('NOP', None), ('NOP', None), ('Timestamp', (3962831618, 3962831618))] |>>>
<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=710 id=7744 flags=DF frag=0 ttl=127 proto=tcp chksum=0xdcef  src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=3000 dport=33574 seq=271589749 ack=3955524768 dataofs=8 flags=PA window=512 chksum=0xbb options=[('NOP', None), ('NOP', None), ('Timestamp', (3962831618, 3962831618))] |<Raw  load='HTTP/1.1 500 Internal Server Error\r\nDate: Sat, 30 Nov 2024 08:55:53 GMT\r\nConnection: close\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 658\r\nX-Request-Id: 7f4bafa0-7590-4b9b-8b8d-70a4fa1ae6c5\r\nX-Runtime: 10.078459\r\n\r\n' |>>>>
HTTP/1.1 500 Internal Server Error
Date: Sat, 30 Nov 2024 08:55:53 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 658
X-Request-Id: 7f4bafa0-7590-4b9b-8b8d-70a4fa1ae6c5
X-Runtime: 10.078459

.....


<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=52 id=15439 flags=DF frag=0 ttl=127 proto=tcp chksum=0xc172  src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=33574 dport=3000 seq=3955524768 ack=271589749 dataofs=8 flags=A window=511 chksum=0xfe28 options=[('NOP', None), ('NOP', None), ('Timestamp', (3962831618, 3962831618))] |>>>
<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=710 id=7744 flags=DF frag=0 ttl=127 proto=tcp chksum=0xdcef  src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=3000 dport=33574 seq=271589749 ack=3955524768 dataofs=8 flags=PA window=512 chksum=0xbb options=[('NOP', None), ('NOP', None), ('Timestamp', (3962831618, 3962831618))] |<Raw  load='<!DOCTYPE html>\n<html>\n<head>\n  <title>Oops - Error 500</title>\n  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n</head>\n<body>\n    <h1>Oops</h1>\n    <p>The software powering this discussion forum encountered an unexpected problem. We apologize for the inconvenience.</p>\n    <p>Detailed information about the error was logged, and an automatic notification generated. We\'ll take a look at it.</p>\n    <p>No further action is necessary. However, if the error condition persists, you can provide additional detail, including steps to reproduce the error, by posting a discussion topic in the site\'s feedback category.</p>\n</body>\n</html>\n' |>>>>
<!DOCTYPE html>
<html>
<head>
  <title>Oops - Error 500</title>
.....

ログにはこれらの行が出力されます。

ネットワークエラーとタイムアウトを示すスクリーンショット。HTTPヘッダーとエラー詳細が含まれています。(AIによるキャプション)

Discourseがコールバックの処理に問題を抱えているように思われます。Discourseの内部で何が起こっているのか、さらに詳しく知る必要があります。

知っている限りのデバッグモードをすべてオンにしましたが、ログに何もヒントが表示されません。

うーん、本当に困っていて、イライラしています :frowning:

皆さん、こんにちは。

だいぶ進みました :slight_smile:
私たちのEAMインフラストラクチャに関係していました…

しかし、今度は次の問題が発生しました :smiley:

私のuserinfotokenは以下のようになっています。

{
  "company-i": "A1",
  "accounting-code": "5806",
  "given_name": "Mister",
  "family_name": "Bean",
  "name": "Mister Bean",
  "departmentnumber": "Covert Operations",
  "salutation": "Dude",
  "description": "Some description",
  "preferredlanguage": "DE",
  "inumber": "723jfio-7zwe8489",
  "employeenumber": "36484332",
  "employeetype": "BigCompany",
  "uid": "f57383",
  "adupn": "f57383@europe.bigcom.corp",
  "uniqueuid": "f57383",
  "uniqueuidq": "f57383",
  "loginname": "f57383",
  "email": "Mister.Bean@bigcom.corp",
  "sub": "f57383",
  "subname": "f57383"
}

そして、ログでこのエラーが発生しています。

ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR:  null value in column "provider_uid" of relation "user_associated_accounts" violates not-null constraint
DETAIL:  Failing row contains (6, oauth2_basic, null, null, 2024-12-03 13:06:49.831182, {"name": "Mister Bean", "email": "Mister.Bean@bigcom.corp", "user..., {"token": "dszghsdhsdfoph", "expires": true, "expir..., {}, 2024-12-03 13:06:49.831362, 2024-12-03 13:06:49.831362).

Discourseは、userinfoendpointからの応答を内部名にマッピングできないようです。

UIから設定しようとしました。

しかし、おそらく間違っていました。

誰か設定方法のヒントを教えていただけますか?

よろしくお願いします。

WS

oauth2 json user id path は入力されていますか?

これらの値が設定されていることを確認してください:https://meta.discourse.org/t/configure-sign-up-and-log-in-with-auth0-using-the-oauth2-basic-plugin/64633#configure-discourse-3

こんにちは。

お返事ありがとうございます。

プロバイダーが provider_nameprovider_uid フィールドを送信していないようです。そのため、Discourse はそれらなしでエントリを作成しようとして、NotNull 違反が発生しています。
しかし、これはプラグイン (oauth2_basic) がこれらの値を (リモート IdP から何も来ない場合) 埋める責任ではないでしょうか?
次のようなものが自動的に使用されることを期待していました。

provider_name: “oauth2_basic”
provider_uid: “1234”

すべてのユーザーログインで… :frowning:

provider_nameoauth2_basic に固定され、provider_uidoauth2 json user id path に入力したものになります。

プロバイダーが返す値に基づいて、サイト設定を ID のパスに設定するだけです。プラグインは、この JSON パスを使用して provider_uid を入力するため、現在空であるか、存在しないパスの場合、値は nil になります。

上記の JSON から、値は sub になるはずです。

「いいね!」 2

でも、そうしました…

おっしゃる通り、パスは「sub」であるべきですが、ここで設定しました。

お待ちください… あなたの言う通りでした。私が愚かでした :frowning:

設定が間違っていました…

これで動作しました!

「いいね!」 2

これらの設定をどこかに保存する方法はありますか?:smiley:
設定のみのバックアップを作成できますか?

それらはデータベースにありますか?

素晴らしいですね。

すべてのサイト設定はデータベースに保存されます。rails console にアクセスできると仮定すると、次のコマンドで設定のリストが表示されます。

SiteSetting.where("name LIKE 'oauth2_%'").pluck(:name, :value)

バックアップを作成することもできます。