OIDC(OpenID Connect)はSSO(Single Sign On)をどのように実現しているか
ritouです。今日はこの話です。
SSO=一度ログインしたら複数RPに一括でログイン可能みたいなイメージに対して、OIDCでの動きは個々のRPがそれぞれ自分達向けのIDTokenを受け取りそれを信用してログイン状態にするだけ。 https://t.co/R4qNOrcY8h
— 👹秋田の猫🐱 (@ritou) 2025年5月9日
ここで扱うSSO(シングルサインオン)とは、一般的に「一度の認証処理で、複数の独立したシステムやサービスへアクセス可能になる仕組み」を指します。 本稿では、このSSOをID連携の主要な実現手段の一つであるOIDC (OpenID Connect) がどのように実現するのかについて解説します。
ID連携を用いないSSOの実現方法:単一セキュリティドメイン内でのアプローチ
まずID連携について触れる前に、単一のセキュリティドメイン(ID管理が一元的に行われる範囲)内で、複数のサービスがSSOと同様の利便性を提供する方法を振り返ってみましょう。 これは、自社で統一されたID体系を運用している比較的規模の大きな企業グループなどを想像すると分かりやすいです。例えば、exampleという企業グループが以下のようなドメインで複数のサービスを提供しているとします。
service1.example.comservice2.example.comservice3.example.net(M&Aによってグループに加わったサービスや、国ごとにドメインが異なるサービスなど、親ドメインが異なるケース)
この場合、*.example.com で提供されるサービス群(service1.example.com、service2.example.com)では、親ドメインである example.com に紐づけられたセッションクッキーをファーストパーティクッキー(1st Party Cookie)として共有することで、SSOに近い挙動を実現できます。
しかし、ドメインが異なる service3.example.net では、このファーストパーティクッキーの仕組みを直接利用できません。従来は、example.com のセッションクッキーをサードパーティクッキー(3rd Party Cookie)として service3.example.net から利用することでセッションを共有するケースもありましたが、近年はプライバシー保護の観点からブラウザによるサードパーティクッキーの制限が強化されており、このアプローチは難しくなっています。そのため、このようなケースでは後述するID連携が使われるケースもあるようです。
複数セキュリティドメインを繋ぐID連携とSSO
ここから本題であるID連携について説明します。 それぞれ独立したセキュリティドメインを持つ複数のサービス間でSSOを実現しようとする場合、ID連携の仕組みが必要となります。 企業が業務で利用する複数のSaaS(Software as a Service)を連携させるケースを想像すると分かりやすいでしょう。以下のような構成は、現代の企業システムにおいて珍しくありません。
- IdP (Identity Provider):
- IDaaS
- RPs (Relying Parties):
- プロジェクト管理ツール
- 社内ドキュメントツール
- ソースコード管理
これらのRPがIdPとどのように連携してSSOを実現するのか、OIDCの認証フローに沿って説明します。
- ユーザーによるRPへのアクセスと認証要求の開始: ユーザーがRP(例: プロジェクト管理ツール)のログイン画面でメールアドレスを入力したり、企業専用のサブドメイン(例: mycompany.project-tool.com)経由でRPにアクセスします。RPはこれを受けて、認証が必要なユーザーを識別しようとします。
- RPからIdPへの認証リクエスト: RPは、IdPに対してOIDCの認証リクエストを送信します。このリクエストには、RPが必要とする情報(スコープ)や、認証後にIdPがユーザーをリダイレクトさせるべきRPのURL(リダイレクトURI)などが含まれます。
- IdPによるユーザー認証: IdPは、まずユーザーがIdP自身で認証済みであるかを確認します。認証されていない場合、またはRPから要求された認証レベル(認証コンテキスト、例: 多要素認証の要求)を満たしていない場合は、ユーザーに対して認証処理(例: ID/パスワード入力、多要素認証)を要求します。既にIdPで認証済みで、かつ要求される認証レベルを満たしていれば、このステップは省略されることがあります。
- IdPからRPへの認証レスポンス (IDトークンの発行): 認証が成功すると、IdPは認証結果としてIDトークン (ID Token) を生成し、RPに提供します。この際、通常は認証コード(Authorization Code)を介して安全にIDトークンがRPに渡されます(Authorization Code Flowの場合)。IDトークンには、認証されたユーザーの識別子や認証に関する情報が含まれます。必要に応じてアクセストークン (Access Token) も発行され、RPはこれを用いて保護されたリソース(例: ユーザープロファイルAPI)へアクセスできます。
- RPによるユーザーのログイン状態確立: RPは受け取ったIDトークンを検証し(署名の検証、発行元の確認など)、その内容に基づいて自サービス内のユーザーアカウントと紐づけます。これにより、RPはユーザーをログイン状態にし、サービスを提供します。
単一セキュリティドメイン内の中央集権的なセッション管理と比較すると、ID連携はより分散的なアーキテクチャと言えます。SAML (Security Assertion Markup Language) を利用する場合も、基本的な考え方や登場人物の役割はOIDCと類似しています。
RPが複数ある場合も、ユーザーが各RPにアクセスするたびに上記の手順(主に2~5)が繰り返されます。 企業でこのようなID連携によるSSOが導入されている環境での挙動例を見てみましょう。
- 最初のアクセス: ユーザーが初めてプロジェクト管理ツール(RP1)にアクセスします。
- RP1はユーザーが未認証であるため、IdPへリダイレクトします。
- ユーザーはIdPでも未認証の場合、IdPのログイン画面で認証情報を入力し、認証を完了します。
- IdPはRP1へ認証情報を返し、RP1はユーザーをログイン状態にします。
- 次のサービスへのアクセス: その後、ユーザーが社内ドキュメントツール(RP2)にアクセスします。
- RP2もユーザーが未認証(RP2に対しては)であるため、IdPへリダイレクトします。
- この時点でユーザーは既にIdPで認証済みであるため、IdPは追加の認証を要求せず、即座にRP2へ認証情報を返します。
- RP2はユーザーをログイン状態にします。ユーザーは再度ログイン操作を行う必要がありませんでした。
企業利用のシナリオでは、情報システム部門などがIdPに対して認証強度やセッションの有効期限といったポリシー(認証コンテキスト)を設定します。ユーザーが一度このポリシーに従ってIdPで認証されれば、連携する各RPは追加の認証なしに利用可能になる、という挙動が一般的です。 このように、個々のRPとIdP間のID連携を組み合わせることで、実質的なSSOが実現されます。
セッション状態の不整合検知と対応
ID連携は便利な仕組みですが、IdPと各RPのセッションは疎結合であるため、セッション状態に不整合が生じる可能性があります。 例えば、前述のシナリオで、ユーザーがIdPで明示的にログアウトしたり、あるいは管理者によってIdPのセッションが無効化された後、既にログイン済みだったRPにアクセスした場合を考えてみましょう。
- ユーザーAがプロジェクト管理ツール(RP1)にアクセスし、IdP経由でログイン。
- その後、何らかの理由でIdP上でユーザーAがログアウトし、同じブラウザでユーザーBがIdPにログインしたとする。(企業利用では稀かもしれませんが、個人向けサービスではあり得ます)
- ユーザーBが次に社内ドキュメントツール(RP2)にアクセス。RP2はIdPにリダイレクトし、IdPはユーザーBの認証情報に基づいてRP2をログイン状態にする。
この時点で、プロジェクト管理ツール(RP1)はユーザーAでログインした状態のまま、社内ドキュメントツール(RP2)はユーザーBでログインしている、という不整合が発生します。もしプロジェクト管理ツール(RP1)がこの変更を検知できず、ユーザーBがアクセスした際にユーザーAのセッションが継続していたら、情報漏洩や意図しない操作に繋がる可能性があります。 このような不整合状態を検知・軽減するために、OIDCではいくつかの仕組みが提案されています。
IdPのログアウト時にRPへ通知する仕組み
IdPでのログアウトイベントを各RPに通知し、RP側でもセッションを終了させることで不整合を防ぐアプローチです。
- OpenID Connect Back-Channel Logout 1.0: IdPでユーザーがログアウトすると、IdPがそのユーザーセッションに関連付けられた各RPのバックエンドエンドポイントに対して直接ログアウト通知(Logout Tokenを送信)を行います。RP側ではこの通知を受け取り、該当ユーザーのセッションを終了させる処理を実装する必要があります。例えば、デジタル庁の「デジタル社会共通機能における認証に関する実装ガイドライン」でもこの仕組みについて言及されています。
- OpenID Connect Front-Channel Logout 1.0: IdPがユーザーのブラウザを介して、各RPのログアウトエンドポイントを(例: iframe内で)順次呼び出すことでログアウトを伝播させる仕組みです。ブラウザの制約(サードパーティクッキー制限など)の影響を受ける可能性があります。
- OpenID Shared Signals and Events (SSE) Framework (旧称: RISC - Risk and Incident Sharing and Coordination): より汎用的で継続的なイベント通知の仕組みです。Back-Channel Logoutと似た目的(セッション無効化通知など)もカバーしますが、アカウント情報の変更、不正アクセスの検知など、より広範なセキュリティイベントをRPに通知するために設計されており、アカウント関連イベント通知の最新のアプローチの一つです。
これらの仕組みは、ユーザーが正規のログアウト操作を行った場合に有効です。ブラウザのクッキーを直接削除するなど、IdPが関知しない形でセッションが無効化された場合には、通知が届かない可能性がある点に留意が必要です。
RPがIdPに定期的にセッション状態の変更有無を問い合わせる仕組み
RPから能動的にIdPへユーザーのセッション状態に変更がないかを確認するアプローチもあります。
- OpenID Connect Session Management 1.0: IdPはIDトークン発行時に session_state というパラメータを付与します。RPは、この session_state とユーザーのブラウザに埋め込んだIdPドメインの非表示iframe、および postMessage APIを利用して、定期的にIdPにセッション状態の変更を確認します。IdP側でセッション状態に変化(例: ログアウト、別ユーザーでのログイン)があれば、RPに通知され、RPは現在のセッションを終了するなどの対応を取ることができます。
このiframeとpostMessageを利用する方法は、策定時期の技術的背景を反映したものです。現在では、ブラウザの新しいAPIを活用した、より洗練されたセッション状態確認の方法が模索されるべき、と言えるでしょう。FedCMなどが関連しそうでしょうか。
まとめ
今回は、ID連携、特にOIDCを用いたSSOの実現方法と、関連する課題について解説しました。
- セキュリティドメインが異なるサービス間でSSOを実現するには、ID連携の仕組みが不可欠です。
- OIDCでは、各RPがIdPに対して認証を要求し、IdPがそれに応答するという基本的なフローを連携先のRPごとに行うことで、結果としてSSOが実現されます。
- ID連携は本質的に疎結合なシステムであるため、IdPとRP間でセッション情報の不整合が発生する可能性がありますが、これを検知・軽減するためのログアウト通知やセッション管理の仕組みも用意されています。
ではまた。