SPAでのSSO認証フローを実装する
概要
このチュートリアルでは、KurocoをバックエンドAPIとして利用するフロントエンドSPA(Single Page Application)において、SSOログインフローの全体を実装する方法を解説します。
SSOによるログインをフロントエンドで利用するではKurocoの基本設定とgrant_tokenの概念を説明していますが、本チュートリアルではフロントエンド側の実装の詳細に焦点を当てます。具体的には、リダイレクトフローの処理、トークンの交換、ログイン後にユーザーの元のページへ復帰する方法について説明します。
以下のシーケンス図は、Microsoft Entra IDをIdPとして使用した場合の完全なフローを示しています。Kurocoで設定されたSSOプロバイダー(OAuth SP、SAML SP、IDaaS SP)であれば、同じパターンが適用されます。

学べること
- SSOリダイレクトフローのエンドツーエンドの仕組み
- SSOリダイレクトをまたいでユーザーの元のURLを保存・復元する方法
grant_tokenをaccess_tokenに交換する方法- ログインを確定し、元のページに遷移する方法
前提条件
- SSOが設定済みのKurocoプロジェクト(OAuth SP、SAML SP、またはIDaaS SP)
- 動的アクセストークンセキュリティと
tokenエンドポイントを持つAPI - フロントエンドSPA(React、Vue、Nuxt、Next.jsなど)
まだKurocoでSSOを設定していない場合は、以下のチュートリアルを先にご参照ください:
フロー概要
SSOログインフローは以下のステップで構成されます:
- 未認証でユーザーが保護されたページにアクセス
- フロントエンドが現在のURLを保存し、KurocoのSSOログインエンドポイントにリダイレクト
- Kurocoがブラウザを外部IdP(例:Entra ID)にリダイレクト
- ユーザーがIdPで認証
- IdPが結果をKurocoに返却し、KurocoがフロントエンドのコールバックURLに
grant_token付きでリダイレクト - フロントエンドが
grant_tokenをaccess_tokenとrefresh_tokenに交換 - フロントエンドがprofileエンドポイントを呼び出してログインを確定
- フロントエンドがユーザーを元のページに遷移
実装
ステップ1:未認証状態の検出
ユーザーが保護されたページにアクセスした際、有効なトークンがあるかを確認します。なければ、ログイン後にリダイレクトできるよう現在のURLを保存します。
const currentPath = window.location.pathname + window.location.search
if (!accessToken) {
sessionStorage.setItem("post_login_redirect", currentPath)
}
リダイレクトURLの保存にはlocalStorageではなくsessionStorageを使用してください。ブラウザタブを閉じたときに自動的にクリアされるため、一時的なログイン状態の管理により適しています。
ステップ2:SSOログインへのリダイレクト
ユーザーをKurocoのSSOログインエンドポイントにリダイレクトします。redirect_uriパラメータは、認証後にKurocoがユーザーを戻すコールバックURLを指定します。
const KUROCO_API = "https://api.example.com"
const CALLBACK_URL = "https://front-end.example.com/auth/callback"
const redirectUri = encodeURIComponent(CALLBACK_URL)
window.location.href = `${KUROCO_API}/sso/login?redirect_uri=${redirectUri}`
redirect_uriは固定の事前登録済みURLでなければなりません。動的に変更しないでください。これはセキュリティ上の要件です。ユーザーの実際の戻り先は、ステップ1で示したようにsessionStorageで別途管理します。
ステップ3:コールバックの処理
コールバックページ(例:/auth/callback)を作成し、URLクエリパラメータからgrant_tokenを取得します。
const params = new URLSearchParams(window.location.search)
const grantToken = params.get("grant_token")
if (!grantToken) {
// エラー処理:ログインページにリダイレクトするか、エラーを表示
throw new Error("コールバックURLにgrant_tokenが存在しません")
}
ステップ4:grant_tokenをaccess_tokenに交換
grant_tokenをKurocoのトークンエンドポイントに送信して、access_tokenとrefresh_tokenを取得します。
const response = await fetch(
`${KUROCO_API}/rcms-api/{api_id}/token`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ grant_token: grantToken }),
}
)
const data = await response.json()
const { access_token, refresh_token } = data
grant_tokenは1回限り有効な短命のトークンです。URLに露出するため、コールバック受信後直ちにアクセストークンに交換する必要があり、再利用はできません。
ステップ5:トークンの保存
トークンを安全に保存します。SPAではメモリ内での保存が推奨されます。
// メモリまたはセキュアなストレージに保存
setAccessToken(access_token)
setRefreshToken(refresh_token)
ステップ6:ログインの確定
新しいアクセストークンでprofileエンドポイントを呼び出し、ログインを確認します。
const profileResponse = await fetch(`${KUROCO_API}/profile`, {
headers: {
Authorization: `Bearer ${access_token}`,
},
})
const user = await profileResponse.json()
ステップ7:元のページへの遷移
sessionStorageから保存済みのURLを取得し、ユーザーを元のページに遷移させます。
const redirectPath =
sessionStorage.getItem("post_login_redirect") || "/"
sessionStorage.removeItem("post_login_redirect")
// ルーターのナビゲーションを使用(例:React Router、Vue Router)
navigate(redirectPath)
トークンリフレッシュ
access_tokenの有効期限が切れた場合は、refresh_tokenを使用して新しいトークンを取得します。リフレッシュも失敗した場合は、SSOフローを再実行します。
const refreshResponse = await fetch(
`${KUROCO_API}/rcms-api/{api_id}/token`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ refresh_token: refreshToken }),
}
)
if (!refreshResponse.ok) {
// リフレッシュ失敗 — SSOフローを再開
sessionStorage.setItem(
"post_login_redirect",
window.location.pathname + window.location.search
)
window.location.href = `${KUROCO_API}/sso/login?redirect_uri=${encodeURIComponent(CALLBACK_URL)}`
return
}
const refreshData = await refreshResponse.json()
setAccessToken(refreshData.access_token)
重要な設計ポイント
redirect_uriは固定
SSOログインエンドポイントに渡すredirect_uriは、常に同じ固定のコールバックURL(例:https://front-end.example.com/auth/callback)でなければなりません。ユーザーの実際の戻り先は、フロントエンド側でsessionStorageを使用して別途管理します。
認証スコープごとに1つのAPI
Kurocoでは、ログインセッションはAPI単位でスコープされます。SSOログインを使用した場合、ユーザーはSSOが設定されたAPIに対してのみ認証されます。認証が必要なすべてのエンドポイントを1つのAPIにまとめることで、セッションの問題を回避できます。
grant_tokenのセキュリティ
grant_tokenは以下の特性を持ちます:
- URLに露出する(クエリパラメータとして)
- 1回のみ有効
- 短命(すぐに期限切れ)
コールバックで受け取ったら、直ちにアクセストークンに交換してください。
関連ドキュメント
サポート
お探しのページは見つかりましたか?解決しない場合は、問い合わせフォームからお問い合わせいただくか、Slackコミュニティにご参加ください。