はじめに
サイト間シングルサインオン(SSO)で、送り出す側が署名付きハンドオフトークンを発行するところまでは前の記事で解説しました。この記事は、その続き。トークンを受け取った側のサイトが何をしているのか、という話です。
受入側のコールバックURLにトークンが届いてから、ユーザーがログイン済みの状態で表示されるまで。ここには「検証して、セッションを作って、元居た場所へ戻す」という一連の流れがあります。地味に見えて、SSOの安全性と体験の良し悪しは、実はこのコールバック側の作り込みで決まるんです。
コールバックが受け取るもの
コールバックURLという入口
各サイトには、ハンドオフトークンを受け取るための専用の入口(コールバックURL)が用意されています。送出側は、このURLにトークンを付けてユーザーをリダイレクトさせます。
ハンドオフトークンを発行
/api/sso/callback?token=...
このコールバックは、いわば「裏口ではなく、鍵のかかった正面玄関」です。誰でもトークンらしき文字列を付けてアクセスできてしまうので、受け取ったものを無条件に信じてはいけません。まず徹底的に検証するところから始まります。
遷移先(戻り先)も一緒に受け取る
コールバックには、トークンに加えて「ログイン後にどのページへ戻すか」という情報も渡されることが多いです。ユーザーはサイトBの特定の商品ページを見たくてリンクを踏んだかもしれません。その意図を汲んで、認証が終わったら本来見たかった場所へ送り届けます。
ただしこの戻り先も、悪意ある外部URLに書き換えられていないか確認が必要です。自サイト内のパスに限定するなどのチェックを挟みます。細かいですが、こういう配慮が地味に効いてきますよね。
トークンを検証する
3つのチェックを順番に
受け取ったトークンは、セッションを作る前に必ず検証します。ハンドオフトークンに仕込んだ「署名・有効期限・使い捨て」を、ここで順番に確かめていきます。
共有シークレットで署名を再計算し、改ざんされていないかを確認
発行時刻から短いTTLを過ぎていないかを確認。期限切れなら拒否
ワンタイムIDが未使用かを確認。使用済みなら拒否し、成功時は使用済みに記録
どれか1つでも通らなければ、その場でエラーにしてセッションは作りません。「疑わしきは拒否」が鉄則です。3つすべてを通過して初めて、このトークンは信頼できる、と判断します。
検証に失敗したときの扱い
失敗時はSSOをあきらめて通常ログインへ
トークンが期限切れだったり不正だったりした場合、無理にSSOを成立させようとしてはいけません。素直にSSOを打ち切り、通常のログイン画面へ誘導します。ユーザーには「もう一度お試しください」程度の穏やかな案内にとどめ、内部の失敗理由は見せないのが安全です。
失敗理由を細かく画面に出すと、攻撃者にヒントを与えてしまいます。ログには詳細を残しつつ、ユーザーへの表示は最小限にする。このバランスが大事なんです。
セッションを確立して戻す
自サイトのセッションを作る
検証を通過したら、いよいよサイトBは自分自身のセッションを作ります。ここがSSOの肝で、サイトAのセッションをそのまま使うのではなく、トークンで受け取ったユーザー識別子をもとに、サイトB側で改めてログイン状態を作り直すんです。
なぜ作り直すのか
Cookieはドメインをまたげません。だからサイトBは、自分のドメインで有効なセッションCookieを自前で発行する必要があります。トークンはあくまで「引き継ぎのきっかけ」であって、セッションそのものではない、というのがポイントです。
こうして発行されたセッションCookieは、以降サイトB内では通常ログインと全く同じように機能します。バックエンドのShopifyストアは共通なので、ポイントも会員価格もそのまま反映されます。
元の目的地へリダイレクト
セッションが確立したら、最初に受け取っておいた戻り先へユーザーを送り届けます。ここでようやく、ユーザーの目には「リンクを踏んだら、ログイン済みで目的のページが開いた」という滑らかな体験が完成します。
裏側では検証・セッション発行・リダイレクトと何段階も走っているのに、体感は一瞬。この「気づかれない滑らかさ」こそが、SSOがうまく設計できているかの答え合わせだと思っています。
全体を1枚で
まとめ
コールバック側の役割は、「受け取ったトークンを疑い、正しければ自サイトのセッションを作り、元の場所へ戻す」ことでした。要点を整理します。
- 無条件に信じない:コールバックは正面玄関。まず検証から
- 3つのチェック:署名・有効期限・使い捨てをすべて通す
- セッションは作り直す:Cookieがドメインをまたげないため、自ドメインで発行
- 失敗は穏やかに:SSOを打ち切り通常ログインへ、詳細は見せない
トークン自体の設計は「署名付きハンドオフトークンの仕組み」に、SSO全体の位置づけは「複数ECサイト間のシングルサインオン設計」にまとめています。対象サイトを増やすときの設定管理は「サイト追加に耐えるSSO設定管理」をご覧ください。