DiscourseConnect ペイロードハッシュエンコーディングの不一致

こんにちは、

Discourse と AWS の作業は初めてのため、どなたかお手伝いいただくか、適切な方向をご教示いただけますと幸いです。このフォーラムの指示に従って、Web サイトに DiscourseConnect を設定しようとしています https://meta.discourse.org/t/discourseconnect-official-single-sign-on-for-discourse-sso/13045/1

実際の例では、Base64 エンコードされたペイロードをハッシュすると、署名と異なる値が出力されます。
ペイロード: bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=(改行は省略)
署名: 2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56
私の HMAC ハッシュ(devglan のオンラインツールで生成): 1ce1494f94484b6f6a092be9b15ccc1cdafb1f8460a3838fbb0e0883c4390471

リターン URL の署名を作成すると、Web サイトと同じ結果が得られるため、なぜ一致しないのかよくわかりません。もしこの理由についてご洞察をいただければ、大変助かります。

例となるペイロード、取得したハッシュ、シークレットキーを共有できますか?(投稿前にテストサイトのシークレットキーを変更してください)

改行は重要であり、署名に影響します。HMAC-SHA256 Generator Online はハッシュを計算する前に改行を削除しているようです。Free Online HMAC Generator / Checker Tool (MD5, SHA-256, SHA-512) - FreeFormatter.com のような他のツールを使用すると、うまくいくかもしれません。

また、URL エンコードされた base64 ペイロードの HMAC を計算する必要があります。つまり、生の新行を含むペイロードのハッシュを計算することはありません。

代わりに、%0A であるべきです。Web フレームワークを使用している場合、ペイロードが自動的にデコードされている可能性がある点に注意してください。この機能を無効にするか、値を再エンコードする方法を見つける必要があります。

「いいね!」 3

この設定を自分のウェブサイトでまだテストしていません。その前に、手順を手動で確認しようとしています。

以前参照されたフォーラム投稿より:

\u003e 以下の設定の場合:
Discourse ドメイン:http://discuss.example.com
DiscourseConnect URL:http://www.example.com/discourse/sso
DiscourseConnect シークレット:d836444a9e4084d5b224a60c208dce14

\u003eユーザーのログイン試行

\u003e* ノンスが生成されます:cb68251eefb5211e58c00ff1395f0c0b
\u003e* 生ペイロードが生成されます:nonce=cb68251eefb5211e58c00ff1395f0c0b
\u003e* ペイロードが Base64 エンコードされます:bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\\n
\u003e* ペイロードが URL エンコードされます:bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D%0A
\u003e* Base64 エンコードされたペイロードに対して HMAC-SHA256 が生成されます:2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56

ここで、私が得た答えが異なります。以前提案された HMAC エンコーダーを、Base64 エンコードされたが URL エンコードされていないペイロードに対して使用したところ、2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56 ではなく d26d5adf900de48890a0c3dcdeec108acd91b44a4b76c90c59955a5ba7b957f7 が得られました。また、URL エンコードされたペイロードに対して使用した場合は、46e749cd26dcabc84eed323ff31f830da674dc87c77a2fcb1b296f76402ea900 となりました。

ただし、チュートリアルの後半、新しいペイロードの作成段階では:

\u003e 署名なしペイロードが生成されます:
nonce=cb68251eefb5211e58c00ff1395f0c0b\u0026name=sam\u0026username=samsam\u0026email=test%40test.com\u0026external_id=hello123\u0026require_activation=true
(順序は問われません。値は URL エンコードされています)

\u003e ペイロードが Base64 エンコードされます
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ==

\u003e ペイロードが URL エンコードされます
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ%3D%3D

\u003e Base64 エンコードされたペイロードに署名が付けられます
3d7e5ac755a87ae3ccf90272644ed2207984db03cf020377c8b92ff51be3abc3

この署名は、Base64 エンコードされたが URL エンコードされていないペイロードをハッシュすることで生成されるため、なぜ最初のペイロードでは機能しないのか少し不安に思っています。

興味深いですね!私もそのオンラインジェネレーターを使って署名を再現できませんでした。Ruby では、以下のように記述すると期待通りに動作します。

pry(main)> OpenSSL::HMAC.hexdigest("sha256", "d836444a9e4084d5b224a60c208dce14", "bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\n")
=> "2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56"

勘で、末尾にキャリッジリターンと改行(つまり Windows 形式の行末)を含んだ文字列で署名を生成してみたところ、freeformatter.com ツールと同じ署名が得られました。

pry(main)> OpenSSL::HMAC.hexdigest("sha256", "d836444a9e4084d5b224a60c208dce14", "bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\r\n")
=> "200c03f1e5d7b859170be102b436d74f761040261be9682b4afec67eb908fabf"

したがって、これらのオンラインツールは避けて、使用するプログラミング言語で最小限の実装を試みるのが最善策だと考えられます。

「いいね!」 6

ご提案ありがとうございます!プロセスの一部を JavaScript で実装し、RunKit で(nodeForge、urlencode、js-base64 ライブラリを使用して)テストしたところ、チュートリアルと同じ結果が返ってきました。

「いいね!」 3