アイデンティティプロバイダーとしてDiscourseを使用しようとした際のログインエラー(SSO、DiscourseConnect)

Python コードを使用して、Use Discourse as an identity provider (SSO, DiscourseConnect) の投稿を参考にしようとしています。以下に示す Python コードは、Discourse インスタンスの https://forum.embeetle.com/session/sso_provider に適切に署名されているはずの URL を出力しますが、代わりに「Login Error」というテキストが表示されるだけです。

https://forum.embeetle.com/logs にはエラーは表示されないため、解決方法がわかりません。これは署名が間違っているということでしょうか?他に何か提案はありますか?

ちなみに、問題が解決したらすぐに SSO シークレットを変更します。

import secrets
import base64
import urllib.parse
import hmac
import hashlib

forum_url = 'https://forum.embeetle.com'
target_url = 'https://embeetle.com/#account'
sso_secret = b'JCLSVcqbAnEPXz2p2xBY'

nonce = secrets.token_urlsafe()
payload = f'nonce={nonce}&return_ssourl={target_url}'
payload_base64 = base64.b64encode(payload.encode('utf-8')).decode()
payload_for_url = urllib.parse.quote(payload_base64)
signature = hmac.new(
    sso_secret, payload_for_url.encode('utf-8'), hashlib.sha256
).hexdigest()

print(f'{forum_url}/session/sso_provider?sso={payload_for_url}&sig={signature}')

このコードは、以下の curl コマンドのようなリンクを生成します。

johan@morla:~/sa> curl 'https://forum.embeetle.com/session/sso_provider?sso=bm9uY2U9bExhRUZjRGFVd0NrNTFkMEVOeGc5dUtKZ0kwNHZNYng5VkpFR0RqRUg0OCZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA%3D%3D&sig=70e647a1baad2e09ef6cdc6d87fae70bc27c6823369be20fd1b11ea536180343'
Login Errorjohan@morla:~/sa>

サイトの設定画面のスクリーンショットを以下に示します。

何が間違っているのでしょうか、またはどのようにデバッグできますか?

さらに一歩進んで、DiscourseConnect の詳細ログをオンにすると、ログにエラーが表示されます。

詳細な SSO ログ: ペイロードの署名解析エラー SSO の署名が無効です: bm9uY2U9YklKeEU1WWw2OFhjSkJydGlwSU15UTRZeVlMeWd6ZzQyUU9mOFo0SWF5QSZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA= 

ログに記載されているペイロードは URL エンコードされておらず(末尾の ‘=’ に注意)、元のペイロードの末尾にある繰り返し %3D が欠落している URL エンコードされたデータの 2 番目の ‘=’ が欠落しています。

了解しました。HMAC-SHA256署名は、URLエンコードされたデータからではなく、base64エンコードされたデータから計算する必要があります。したがって、正しいコードは次のとおりです。

import secrets
import base64
import urllib.parse
import hmac
import hashlib

forum_url = 'https://forum.embeetle.com'
target_url = 'https://embeetle.com/#account'
sso_secret = b'JCLSVcqbAnEPXz2p2xBY'

nonce = secrets.token_urlsafe()
payload = f'nonce={nonce}&return_sso_url={target_url}'
payload_base64 = base64.b64encode(payload.encode('utf-8')).decode()
payload_for_url = urllib.parse.quote(payload_base64)

signature = hmac.new(
    sso_secret, payload_base64.encode('utf-8'), hashlib.sha256
).hexdigest()

print(f'{forum_url}/session/sso_provider?sso={payload_for_url}&sig={signature}')

次に、リダイレクトの処理、ノンスの確認など、残りの作業を行います。続く…

「いいね!」 1

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.