アドオンへのシングルサインオン
最終更新日 2025年02月13日(木)
Table of Contents
クラウドサービスでは、リソースを管理するためにユーザーがログインする Web UI 管理パネルを提供することがあります。たとえば、Memcache クラウドサービスでは、Web ベースで使用状況を分析したりキャッシュをフラッシュしたりするためのダッシュボードを提供します。
このドキュメントの説明に従ってシングルサインオンを実装すれば、Heroku の顧客がダッシュボードにアクセスできるようになります。
まとめ
Heroku では、ソルト (共有秘密鍵)、タイムスタンプ、およびリソース ID を組み合わせることによってシングルサインオントークンを生成します。ユーザーのブラウザは、このトークンを使用してサイトにリダイレクトされます。サイトでは、トークンの真正性を確認した後、ユーザーセッションを作成し、リソースの管理パネルにユーザーをルーティングすることができます。
SSO のテスト
SSO やその他のアドオン統合機能をテストするために、アドオンの <your slug>-staging
バージョンを作成することをお勧めします。この <your slug>-staging
アドオンは、統合インフラストラクチャのステージングバージョンを指すようにしてください。
ソルト、タイムスタンプ、トークン
アドオンマニフェストは、アドオンを記述する JSON ドキュメントです。
アドオン (および、結果としてそのマニフェスト) を作成すると、ランダムに生成された sso_salt がマニフェストのフィールドに含められます。
SSO リクエストには 2 つのトークンがあり、使用しているアドオンパートナー API のバージョンに応じて、どちらか 1 つを使用してユーザーをログインさせることができます。v3 トークンは resource_token
という名前です。
リソーストークンの作成
アドオンパートナー API の v3 では、resource_token は次の式を使用して作成されます。
resource_token = sha1(resource_uuid + ':' + salt + ':' + timestamp)
resource_uuid
は、プロビジョニングリクエストでリソースに対して指定する UUID です。salt
はアドオンマニフェストから取得されます。timestamp
は POST リクエストのパラメータに含められます。
たとえば、入力が次のようであるとします。
resource_uuid = 11111111-1111-1111-1111-111111111111
salt = 2f97bfa52ca102f8874716e2eb1d3b4920ad0be4
timestamp = 1267597772
…SSO resource_token は次のようになります。
SHA1("11111111-1111-1111-1111-111111111111:2f97bfa52ca102f8874716e2eb1d3b4920ad0be4:1267597772") =
4e9ce13ca328c6f3e2857b7de1724fd6c7c1c423
リダイレクト時のユーザーのサインイン
アドオンメニューでアドオンをクリックしたユーザーは、マニフェストで定義された URL に HTTP POST 経由で転送されます。
リクエストは次のようになります。
POST <production/sso_url>
resource_id=<resource_id>&resource_token=<resource_token>&id=<id>&token=<token>×tamp=<timestamp>&nav-data=<nav data>&email=<user's email address>
示されているように、データは POST 本体でフォームエンコードされます。
sso_url
はアドオンマニフェストから取得されます。resource_id
は、プロビジョニング呼び出しでリソースに対して指定する UUID です。timestamp
は UNIX エポックタイムスタンプです。resource_token
は上記の式を使用して計算されます。resource_id
とresource_token
を使用するときは、id
とtoken
の値は無視してください。
安全に無視できる従来のフィールドは次のとおりです。
id
とtoken
– v1 ソルトトークンにのみ使用されます。アドオンパートナー API の v3 を使用している場合は無視してください。nav-data
には、Heroku のレイアウトで現在のアプリに適したビューを構築できるよう、現在のアプリ名やインストールされているアドオンなどの情報が含まれています。
計算した SHA1 ハッシュが、resource_token
で渡されたものと一致しない場合、ユーザーには HTTP ステータスコード 403 のページが表示されます。timestamp
が 5 分前より古い場合にも 403 が表示されます。
HTTP ステータスコード 403 は、ユーザーがこのページへのアクセスを許可されなかったことを示します。このコードを返した上で、(リクエストが正当なものと確信している場合はサポートに連絡するようユーザーに提案するなどの) わかりやすいメッセージを記した通常のページを表示することができます。
timestamp
が現在の時刻で SHA1 ハッシュが一致する場合、ユーザーは対象のリソースへのアクセスを許可されます。
通常使用する何らかの方法でユーザーセッションを作成し、場合によっては Cookie を設定します。Heroku の顧客の場合、通常のスタンドアロンサービス経由でログインするユーザーとは表示内容が多少異なります。そのため、セッションでは、これが Heroku のシングルサインオンであることを保存します。ユーザーアクセスの状況は随時変化するため、この SSO データが信頼できるのはセッションが終了するまでの間だけです。セッションの有効期間を 90 分に制限することもお勧めします。
サイトのレイアウトにユーザー情報を表示する
SSO リクエストで送信され、サイトでユーザーに合ったコンテキストを表示するために役立つ、フォームエンコードされたパラメータは他にもあります。これらには以下のものが含まれます。
user
- 現在のユーザーのメールアドレスapp
- ユーザーの転送元であるスコープ内の Heroku アプリ名。
これらを使用して、テンプレートにユーザー情報を入力したり (場合によっては、ユーザーの Gravatar を取得したり)、コンテキスト内のアプリのダッシュボードにリンクしたりできます。そのためには、パラメータが &app=your-app-name
のように渡された場合、https://dashboard.heroku.com/apps/your-app-name
にリンクします。
サンプルコード
次に示すのは、Ruby/Sinatra で記述された v3 シングルサインオンエンドポイントのサンプル実装です。
post "/heroku/sso" do
pre_token = params[:resource_id] + ':' + HEROKU_SSO_SALT + ':' + params[:timestamp]
token = Digest::SHA1.hexdigest(pre_token).to_s
halt 403 if token != params[:resource_token]
halt 403 if params[:timestamp].to_i < (Time.now - 2*60).to_i
account = Account.find(params[:resource_id])
halt 404 unless account
session[:user] = account.id
session[:heroku_sso] = true
redirect "/dashboard"
end
関連性のないページ要素の削除
サイトでシングルサインオンリクエストを受理したら、最後の手順として、Heroku の顧客の SSO セッションに関連しないページ要素を非表示化または無効化します。次のような例があります。
- パスワードの変更
- アカウント名の変更
- 請求情報の更新
- ログアウト
これらの項目はすべて、Heroku の顧客が Heroku Dashboard および CLI から管理します。これらの情報は Heroku のインフラストラクチャにあり、アドオンからは更新できません。