メインコンテンツにスキップ

CasdoorでのSteam OAuthとTelegram OAuth: OIDC経由での非標準ソーシャルログインの追加

· 1分読む
Yang Luo
Casdoor Maintainer

"Steam OAuth"は存在しません。SteamはOpenID 2.0でユーザーをサインインし、64ビットのSteamIDを提供するだけです。Telegramの従来のLogin WidgetもOAuthではありません。ページにはユーザーフィールドと、ボットトークンで検証するHMAC-SHA256ハッシュが渡されます。現在、Telegramはoauth.telegram.orgで実際のOpenID Connectプロバイダーも運営しています。アプリとこれらのプロバイダーの間にCasdoorを配置すると、Casdoorがプロトコル固有のチェックを行い、アプリはGoogleやGitHubの場合と同様に、Casdoorとの通信にOpenID Connectのみを使用します。

プロバイダーの概要​

プロバイダープロトコルユーザーを識別するものメールアドレスの利用可否Casdoorプロバイダータイプ
Steamhttps://steamcommunity.com/openid/loginでのOpenID 2.0、およびプロフィール用のSteam Web APIクレームされたID https://steamcommunity.com/openid/id/<steamid>から取得されるSteamID64いいえSteam
Telegram (Login Widget)ボットトークンのSHA-256をキーとするHMAC-SHA256で署名されたウィジェットデータTelegramユーザーidいいえTelegram
Telegram (OpenID Connect)https://oauth.telegram.orgでのPKCE付きOIDC認可コードフローIDトークンのsubクレームメールクレームなし。phoneスコープで電話番号を取得可能Custom
X (Twitter)PKCE付きOAuth 2.0認可コード/2/users/meからのXユーザーIDCasdoorのデフォルトスコープでは不可Twitter
FacebookOAuth 2.0認可コードアプリスコープのユーザーIDプロフィールに有効なプライマリメールがある場合のみFacebook

この記事の残りの部分では、各プロトコルが実際に返す内容と、Casdoorがそれをどのように処理するかについて説明します。

Steam: OpenID 2.0、OAuthなし​

Steamの開発者ページでは、SteamをOpenIDプロバイダーとして説明しています。サイトはユーザーをSteamに送信し、Steamはhttps://steamcommunity.com/openid/id/<steamid>形式のクレームされたIDを送り返します。末尾の数字はユーザーの64ビットSteamIDです。認可コード、アクセストークン、スコープ、メールアドレスはありません。OpenIDレスポンスにもWeb APIプロフィールにも含まれていません。

そのため、"steam oauth"を検索しても有用な情報は得られません。プロトコルはOpenID Connectの前身であるOpenID 2.0であり、OAuth 2.0またはOIDCクライアントライブラリではSteamと直接通信できないからです。

Steamサインイン時にCasdoorが実行すること:

  1. Casdoorのサインインページは、openid.realmをCasdoorのオリジンに、openid.return_toをCasdoorの/callbackページに設定して、https://steamcommunity.com/openid/loginへのOpenID 2.0 checkid_setupリクエストを作成します。
  2. Steamからリダイレクトされると、Casdoorは署名されたフィールドをopenid.mode=check_authenticationとともにSteamにPOSTします。Steamがis_valid:trueと回答した場合のみ続行します。また、openid.claimed_idがsteamcommunity.com/openid/id/<digits>パターンと一致することを確認し、そこからSteamIDを抽出します。
  3. Client secretとして入力したSteam Web APIキーを使用して、CasdoorはISteamUser/GetPlayerSummariesを呼び出し、ペルソナ名とアバターを取得します。

結果として作成される Casdoor ユーザーは、SteamID64 をユーザー名、Steam のペルソナ名を表示名、Steam のアバター画像を使用します。メールフィールドは空のままです。Casdoor は基盤ライブラリが挿入するプレースホルダーテキストを意図的に破棄します。アプリでメールアドレスが必要な場合は、サインアップ後に収集してください。

セットアップは 2 分で完了します: Steam のキーページで Casdoor ドメイン用の Web API キーを登録し、Steam タイプのプロバイダーを作成して、そのキーをクライアントシークレットとして貼り付けます。手順については Steam プロバイダーガイド を参照してください。

Telegram: ログインウィジェットとその HMAC チェック​

従来の Telegram ログインは JavaScript ウィジェットです。@BotFather でボットを作成し、/setdomain を使用してドメインをリンクし、ウィジェットを埋め込みます。ユーザーが Telegram で確認すると、ウィジェットは data-auth-url にある URL にリダイレクトするか、JavaScript 関数を呼び出し、id、first_name、last_name、username、photo_url、auth_date および hash を渡します。

このペイロードにはトークンが含まれていません。誰でもこれらのフィールドを URL に入力できるため、サーバーは hash を検証する必要があります。Telegram の公式ドキュメントに記載されているチェックは次のように機能します:

data_check_string = all received fields except hash,
as key=value, sorted by key, joined with "\n"
secret_key = SHA256(bot_token)
valid = hex(HMAC_SHA256(data_check_string, secret_key)) == hash

Telegram では、古いデータの再生を防ぐために auth_date もチェックするよう推奨していますが、許容範囲(ウィンドウ)の設定はあなた次第です。

Casdoor では、Telegram プロバイダータイプはボットユーザー名(@ なし)を Client ID として、ボットトークンを Client secret として受け取ります。ユーザーが Telegram ボタンをクリックすると、Casdoor は独自の /telegram-login ページを開き、そこでは telegram.org から telegram-widget.js を読み込み、あなたのボットユーザー名を使用し、data-auth-url を Casdoor の /callback に向けます。コールバックはフィールドを収集し、その後 Casdoor バックエンドは以下を実行します:

  • hash を除くすべてのフィールドからデータチェック文字列を再構築し、それをソートして、HMAC-SHA256 が hash と一致するかを SHA256(bot token) をキーとして比較します;
  • auth_date が 24 時間以上前の場合、データを拒否します;
  • 数値の Telegram id をアイデンティティとして、username をユーザー名として、ファーストネームとラストネームを表示名として、photo_url をアバターとして使用します。

Telegram のユーザー名はオプションです。ユーザーにユーザー名がない場合、Casdoor は telegram_<id> を生成し、これはすべてのサインインで同じままです。ウィジェットはメールアドレスや電話番号を送信しないため、Casdoor 内の Telegram のみのユーザーにはどちらもありません。BotFather の手順については Telegram プロバイダーガイド を参照してください。

Telegram は OpenID Connect も提供するようになりました​

Telegram の「Log In With Telegram」ページでは、標準的な OpenID Connect フローが文書化されており、旧 iframe ウィジェットのドキュメントはアーカイブページに移行しました。Telegram のドキュメントからの事実:

  • ディスカバリードキュメント: https://oauth.telegram.org/.well-known/openid-configuration。認可エンドポイント https://oauth.telegram.org/auth、トークンエンドポイント https://oauth.telegram.org/token、鍵は https://oauth.telegram.org/.well-known/jwks.json にあります。
  • @BotFather でボットの Login Widget 設定を開き、許可された URL(オリジンと正確なリダイレクト URI)を登録し、クライアント ID とクライアントシークレットを取得します。
  • 認可コードフロー、S256 を推奨する PKCE。トークンリクエストでは、クライアント ID とシークレットを使用した HTTP Basic 認証が用いられます。
  • スコープ: openid は必須です; profile は名前、preferred_username および picture を追加します; phone はユーザーの同意を得て phone_number を追加します。Email クレームはありません。
  • UserInfo エンドポイントは存在しません。すべてのユーザーデータは ID トークンに含まれており、その iss は https://oauth.telegram.org、aud はあなたのボット ID です。

このフローは Casdoor の カスタム OAuth プロバイダー で接続できます。Auth URL と Token URL を上記のエンドポイントに設定し、Scope を openid profile に設定し(必要に応じて phone を追加)、Enable PKCE をオンにし、UserInfo URL は空のままにします。BotFather で Casdoor の https://<your-casdoor-host>/callback を許可された URL として登録します。UserInfo URL がない場合、Casdoor はトークンレスポンス内の ID トークンからユーザー情報を取得します: sub を必須とし、期限切れのトークンを拒否し、aud にクライアント ID が含まれていることを確認します。ユーザーマッピングがない場合、sub がユーザー ID、preferred_username がユーザー名、name が表示名、picture がアバターとなり、phone_number が電話番号に設定されます。Casdoor のサインインページは、認可 URL が oauth.telegram.org を指すカスタムプロバイダーを認識し、OAuth の state を短く保ちます。

ウィジェット経由でサインインした Telegram ユーザーと、OIDC 経由でサインインした同一人物は、自動的に同じ Casdoor ユーザーとして扱われないことに注意してください。ウィジェットでのアイデンティティは数値の id ですが、OIDC でのアイデンティティは sub であり、Telegram 自身の例でも両者の値は異なることが示されています。アプリケーションごとにどちらか一方の方法を選択してください。

X (Twitter) と Facebook​

これら 2 つは通常の OAuth 2.0 ですが、それぞれ知っておくべき詳細があります。

X は OAuth 2.0 の認可 URL で PKCE チャレンジを要求します。Casdoor の Twitter タイプはサインインごとに新しいコードベリファイアを生成し、S256 チャレンジを送信して、トークン交換時にベリファイアを渡すため、クライアント ID とシークレット以外に設定項目はありません。Casdoor は users.read tweet.read スコープを要求し、ユーザー ID、ハンドルおよび表示名を提供する /2/users/me からユーザー情報を読み取ります。Email フィールドは要求されないため、メールアドレスを持たない X ユーザーへの対応を計画してください。アプリ設定については Twitter プロバイダーガイド を参照してください。

Facebook はアプリスコープ付きのユーザー ID を返します: 同じ人物でも Facebook アプリごとに異なる ID を持つため、新しい Facebook アプリに移行すると、メールでリンクしない限り、ユーザーは以前のレコードと一致しません。Casdoor は email,public_profile を要求し、Graph API から id、name、picture および email を読み取ります。有効なアドレスがないプロフィールの場合、Facebook は email を省略します。Facebook プロバイダーガイド を参照してください。

アプリがこれをすべて見る方法: プレーン OIDC​

アプリケーションは Steam、Telegram、X または Facebook と直接通信しません。アプリケーションは Casdoor の OIDC クライアントであり、Casdoor の発行元 https://<your-casdoor-host>/.well-known/openid-configuration を使用して一度設定します。Casdoor アプリケーションの Providers タブでソーシャルプロバイダーを追加すると、それらのボタンが Casdoor のサインインページに表示されます。

これらのいずれかでサインインした後、Casdoor はユーザーを検索または作成し、アプリケーションとの通常の認可コードフローを完了します。アプリケーションが受け取る ID トークンは Casdoor によって署名されており、その sub は SteamID や Telegram ID ではなく、Casdoor ユーザー ID です。したがって、アプリケーションには OpenID 2.0 ライブラリ、HMAC コード、プロバイダーごとの PKCE の特殊な処理、およびメールアドレスを持たないユーザーに対する特別なケース対応は不要です。元のプロバイダー ID は、必要に応じて参照できるよう、例えば steam や telegram フィールドなど、Casdoor ユーザーに保存されます。

事前に計画しておくべき点がいくつかあります:

  • アカウントリンク。 Casdoor は、検証済みメール、検証済み電話番号、またはユーザー名を通じて、既存のユーザーとソーシャルサインインをリンクします。順序はアプリケーションのバインディングルールによって決まります。Steam とウィジェットベースの Telegram はメールも電話番号も提供しないため、すでにサインインしているアカウントからユーザーがプロバイダーをリンクしない限り、別のユーザーを作成します。Casdoor がアカウントをリンクする方法を参照してください。
  • 追加のプロフィールフィールド。 Goth ベースの Steam タイプやカスタムプロバイダーなど、生データを渡すプロバイダーは、ユーザーマッピングを通じてより多くのユーザーフィールドを設定できます。
  • クライアント側。 標準的なライブラリであれば、Casdoor に対して動作します。標準 OIDC クライアントの接続ではエンドポイントが一覧化されており、Spring Boot SSO with OIDCの記事では完全なアプリ例を示しています。

参考資料​