SAML・OAuth2・OIDCの違いを整理する――認証と認可の概念から始める入門
Webサービスに「Googleでログイン」ボタンがあったり、会社のPCで一度ログインすれば社内のすべてのシステムにアクセスできたりします。こういった「別々のシステム間でID情報を連携する仕組み」を総称してID連携(またはフェデレーション)と呼びます。
SAML・OAuth2・OIDCは、このID連携を実現するための代表的な標準仕様です。3つが並んで語られるのは、解決しようとしている問題領域が重なっているからです。ただし目的は微妙に異なり、それを混同したまま実装するとセキュリティ上の問題につながります。
認証まわりの技術選定で「なんとなくOIDCにした」「SAMLとOIDCどっちにすればいいか聞かれても答えられない」という状況は珍しくありません。本記事では、まず「認証」と「認可」の違いを土台に置き、SAML・OAuth2・OIDCそれぞれの目的・仕組み・デメリット・セキュリティリスクを整理します。
1. 土台:認証と認可は別物
ここがズレたままだと、3つのプロトコルの位置づけが永遠に整理できません。
認証(Authentication)
「あなたは誰ですか」を確認するプロセスです。
システムに対して「私はAさんです」と主張し、それを検証します。パスワード照合・指紋認証・証明書検証などがその手段です。
認可(Authorization)
「何をしていいか」を決めるプロセスです。
認証済みのAさんが「このリソースにアクセスできるか」「この操作を実行できるか」を判断します。RBACやACLはここに属する概念です。
混同すると何が困るか
たとえば、OAuth2は「認可フレームワーク」であり、認証のためのプロトコルではありません。アクセストークンを取得できても「それが誰のトークンか」はわかりません。にもかかわらずトークン取得をもってログイン完了とする実装が存在しており、別のユーザーのトークンをすり替えることで第三者がログインできてしまうケースがあります。詳細は後述します。
整理: 認証がなければ認可は成立しません。順序として認証が先にあり、認可はその結果に基づいて機能します。
2. SAML(Security Assertion Markup Language)
概要
SAMLはOASISが策定した、認証情報をXMLで交換するための標準プロトコルです。SAML 1.0は2002年11月、現行のSAML 2.0は2005年3月にOASIS標準として承認されています(OASIS SAML仕様)。
主に企業間のシングルサインオン(SSO)に使われます。登場人物は3つです。
- Principal(主体):エンドユーザー
- IdP(Identity Provider):認証を行う側(例:社内ADやOkta)
- SP(Service Provider):サービスを提供する側(例:Salesforce、Slack)
仕組み(SP-Initiatedフロー)
1. ユーザーがSPにアクセス
2. SPがIdPにリダイレクト(SAMLリクエスト送信)
3. IdPがユーザーを認証(ログイン画面等)
4. IdPがSAML Assertionを生成してSPに送信
5. SPがAssertionを検証してアクセス許可
SAML AssertionはXML文書で、ユーザーの属性(メールアドレス、所属部署など)と認証結果を含みます。デジタル署名で改ざんを防止します。
ユースケース
- 企業間のフェデレーション(A社の社員がB社のシステムにSSOでアクセス)
- 既存エンタープライズIdP(Active Directory Federation Servicesなど)との連携
- SaaSへの企業アカウントSSO(Salesforce、AWS IAM Identity Center等)
デメリット
実装コストが高い。
XMLベースの仕様は複雑で、AssertionのパースやXML署名検証に誤りが生じやすい傾向があります。ライブラリへの依存度が高く、ライブラリ自体の脆弱性がそのまま影響します。
モバイルアプリ・SPAとの相性が悪い。
SAMLはブラウザのリダイレクトを前提に設計されています。ネイティブアプリやAPIファーストの構成とは根本的に相性が悪く、無理に使うとアーキテクチャが歪みます。
仕様が重く、柔軟性に乏しい。
XMLスキーマの制約が強く、新しいユースケースへの対応が遅いです。新規システムでゼロから選ぶ場面では候補から外れることが増えています。
セキュリティリスクと注意点
① XML署名ラッピング攻撃(XSW攻撃)
SAMLの署名検証に実装上の欠陥があると、攻撃者が署名済みAssertionに悪意のある要素を挿入し、検証をすり抜けることができます。SAMLライブラリは定期的にアップデートし、CVEベースで既知の脆弱性を追跡してください。
② リプレイ攻撃(Assertionの再利用)
有効期限内のAssertionを傍受して再利用する攻撃です。SPはAssertionのIDを一時的に保存し、二重使用を拒否する実装(InResponseTo検証など)が必要です。
③ オープンリダイレクト(リダイレクト先の検証不備)
IdPがSPからのリダイレクト先URLを適切に検証しないと、攻撃者が任意のURLに誘導できます。IdPはSP登録時のURLと厳密に照合してください。
④ 証明書の管理不備
Assertionの署名検証に使う証明書が期限切れになるとSSOが突然停止します。ローテーション計画を事前に策定し、有効期限の監視を組み込んでおいてください。
3. OAuth2(OAuth 2.0)
概要
OAuth2は2012年10月にRFC 6749として策定された認可フレームワークです(RFC 6749)。「第三者アプリケーションに、リソースへのアクセスを安全に委譲する」ことが目的であり、認証プロトコルではありません。
登場人物は4つです。
- Resource Owner:リソースの所有者(エンドユーザー)
- Client:リソースにアクセスしたいアプリケーション
- Authorization Server:アクセストークンを発行するサーバー
- Resource Server:実際のリソースを持つサーバー(API等)
仕組み(Authorization Codeフロー)
1. ユーザーがClientアプリを操作
2. ClientがAuthorization Serverにリダイレクト(スコープを指定)
3. ユーザーが認可画面で「許可」
4. Authorization ServerがClientに認可コードを返す
5. Clientがコードをアクセストークンと交換(バックチャネル通信)
6. ClientがアクセストークンでResource Serverを呼び出す
この設計の核心は「ユーザーのパスワードをClientに渡さない」ことです。トークンというProxy経由で権限を委譲します。
ユースケース
- 「Googleドライブのファイルを読み込む」API連携
- 「カレンダーアプリにGmailへのアクセスを許可する」権限委譲
- サードパーティ開発者向けのAPIアクセス管理
デメリット
認証には使えない(最重要)。
OAuth2のアクセストークンは「リソースへのアクセス権」を表すだけで、「誰がログインしているか」を保証しません。アクセストークンの取得をもってログイン完了とする実装が存在しており、別のユーザーのトークンをすり替えることで第三者がログインできてしまうケースがあります。詳細はセキュリティリスクの①で説明します。
グラントタイプが多く、選択ミスが起きやすい。
Authorization Code・Client Credentials・Device Code・Implicit(現在は非推奨)など複数のフローがあります。なお、OAuth 2.1(現在ドラフト段階)ではImplicitとResource Owner Password Credentialsは削除される予定です。
トークン失効管理が煩雑。
アクセストークンの有効期限管理、リフレッシュトークンのローテーション、失効(Revocation / RFC 7009)の実装は仕様で定義されていますが実装者に委ねられる部分が多く、ミスが起きやすいです。
セキュリティリスクと注意点
① アクセストークンを使ったなりすましログイン
Client Aが取得したアクセストークンをClient Bに渡し、Client Bがそのトークンでログイン処理を行うと、本来のリソースオーナーとは別人としてログインできてしまいます。OAuth2単体でログイン機能を実装してはいけません。ユーザー認証にはOIDCを使ってください。
② CSRF攻撃(stateパラメーター未検証)
stateパラメーターはCSRF対策のために必須です。省略・固定値にすると、攻撃者が細工したリクエストでユーザーを攻撃者のアカウントにリンクさせることができます(アカウント乗っ取りの一形態)。stateは毎回ランダムに生成・検証してください。
③ 認可コードの傍受(PKCE未使用)
SPAやネイティブアプリではclient_secretを安全に保管できないため、認可コードが傍受された場合のリスクがあります。PKCE(Proof Key for Code Exchange / RFC 7636)を必ず使用してください。現在のベストプラクティスではPublic ClientにはPKCEが必須です。
④ オープンリダイレクト(redirect_uri検証不備)
redirect_uriの検証が不十分だと、攻撃者が任意のURLに認可コードやトークンを送り込めます。Authorization Serverは登録済みURIと完全一致で照合してください(前方一致はNGです)。
⑤ リフレッシュトークンの漏洩
リフレッシュトークンは長命であるため、漏洩した場合の影響が大きくなります。Refresh Token Rotationを実装し、使用済みのリフレッシュトークンは即時無効化することが推奨されています(OAuth 2.0 Security Best Current Practice / RFC 9700)。
4. OIDC(OpenID Connect)
概要
OIDCは2014年にOpenID Foundationが策定した、OAuth2の上に認証レイヤーを追加した仕様です(OpenID Connect Core 1.0)。OAuth2が「認可」しかできないという問題を解決するために設計されました。
OAuth2でアクセストークンを取得できても「それが誰のトークンか」はわかりません。OIDCはこの問題を解決するためにIDトークン(JWT形式)を導入しました。
仕組み
基本的なフローはOAuth2のAuthorization Codeフローと同じですが、以下が追加されます。
- scopeに「openid」を含めることでOIDCモードになる
- Authorization Serverがアクセストークンに加えてIDトークンを発行
- IDトークンはJWT形式で、sub(ユーザー識別子)・iss(発行者)・
aud(宛先)・exp(有効期限)などのClaimを含む
- ClientはIDトークンの署名を検証し、ユーザーを認証する
OIDCの重要な概念:
- UserInfoエンドポイント:アクセストークンを使ってユーザー属性を取得するAPI
- Discovery(.well-known/openid-configuration):IdPのエンドポイント情報を自動取得する仕組み
- JWKSエンドポイント:IDトークンの署名検証に使う公開鍵を配布するAPI
ユースケース
- Webアプリへのソーシャルログイン(「Googleでログイン」「GitHubでログイン」)
- マイクロサービス間での認証情報の受け渡し
- モバイルアプリのユーザー認証
デメリット
OAuth2の複雑さを引き継ぐ。
OIDCはOAuth2の上位互換であり、OAuth2の複雑なフロー選択・パラメーター管理をそのまま扱う必要があります。「OIDCを使えばOAuth2を知らなくていい」わけではありません。
IDトークン検証を省略する実装ミスが多い。
IDトークンを取得したことに満足して、署名検証・iss/aud/expのクレーム検証を省略する実装が後を絶ちません。検証を省くとIDトークンの偽造・改ざんを検知できなくなります。
IdP障害時の可用性リスク。
外部IdP(Google・Microsoft等)に認証を依存すると、IdP障害時にサービスが完全にログイン不能になります。障害時のフォールバック設計(ローカル認証との併用等)を検討する必要があります。
セッション管理の複雑性。
OIDCのセッションとアプリケーション側のセッションが独立して存在するため、ログアウト処理が複雑になります。Front-Channel LogoutとBack-Channel Logoutの設計を理解していないと、片方だけがログアウトされた状態が発生します。
セキュリティリスクと注意点
① IDトークンの署名検証省略
最も多い実装ミスです。IDトークンはJWTであり、Base64デコードすれば中身を読めますが、署名検証なしに信頼してはいけません。JWKSエンドポイントから取得した公開鍵で必ず検証してください。
② nonce検証の省略(リプレイ攻撃)
OIDCではリクエスト時にnonce(ワンタイム値)を生成し、IDトークンのnonceクレームと照合することでリプレイ攻撃を防ぎます。これを省略すると、傍受したIDトークンの再利用が可能になります。
③ aud(audience)クレームの未検証
IDトークンのaudには、そのトークンが向けられたClientのIDが含まれます。これを検証しないと、他のClientに発行されたIDトークンを自分のサービスで使われてしまいます(Confused Deputy問題)。
④ PKCEとstateの両立
OIDCでもOAuth2と同様にstateと(Public Clientでは)PKCEが必要です。ライブラリに任せていると、デフォルト設定で省略されているケースがあります。使用しているSDKの設定を確認してください。
⑤ 過剰なスコープ要求
openid profile email phone addressを一括で要求する実装が多いですが、必要最小限のスコープに限定してください(最小権限の原則)。不要なユーザー情報を取得・保管すると、情報漏洩時の影響範囲が広がります。
5. 3つを並べて比較
| SAML | OAuth2 | OIDC | |
|---|---|---|---|
| 策定年 | 2005年(v2.0) | 2012年(RFC 6749) | 2014年 |
| 主目的 | 認証(SSO) | 認可(委譲) | 認証+認可 |
| 認証できるか | ✅ | ❌ | ✅ |
| 認可できるか | △(属性ベース) | ✅ | ✅ |
| トークン形式 | XML Assertion | Opaque Token / JWT | JWT(IDトークン) |
| トランスポート | HTTPリダイレクト(XML) | HTTP(JSON) | HTTP(JSON) |
| モバイル対応 | ❌ 相性が悪い | ✅ | ✅ |
| 主なユースケース | 企業間SSO | APIアクセス委譲 | ソーシャルログイン・Webアプリ認証 |
| 実装難易度 | 高(XMLが複雑) | 中(フロー選択が多い) | 中〜高(OAuth2+検証実装) |
6. どれを選ぶか
企業間SSOを実装したい → SAML
既存の企業IdP(AD FS・Okta・Azure AD)との連携が前提であれば、SAMLが現実的な選択肢になります。エンタープライズSaaSの多くがSAMLを標準でサポートしているため、互換性の観点からSAMLを選ぶケースは多いです。ただし、新規システムでゼロから設計するならOIDCも選択肢に入ります。
APIへのアクセス権限を第三者アプリに委譲したい → OAuth2
「ユーザーの代わりにAPIを叩く」権限を外部アプリに渡す用途であれば、OAuth2のAuthorization Codeフロー(+PKCE)が適切です。繰り返しになりますが、OAuth2単体でユーザーのログイン処理を実装してはいけません。
Webアプリ・モバイルアプリのログイン機能を実装したい → OIDC
「ユーザーが誰か」を確認してセッションを張る用途はOIDCが正解です。「Googleでログイン」「GitHubでログイン」はすべてOIDCです。新規開発でSAMLが必須でなければ、OIDCを選ぶのが現代のデファクトスタンダードです。
マイクロサービス間の認証 → OIDC(またはOAuth2 Client Credentials)
サービス間通信(Machine-to-Machine)の場合はOAuth2のClient Credentialsフローが適切です。ユーザー認証が伴う場合はOIDCのJWT検証を組み合わせる構成が一般的です。
まとめ
3つのプロトコルの違いを一言で言うと以下になります。
- SAML:企業間SSOのための認証プロトコル。XMLが重いが枯れた技術として企業に広く普及しています。
- OAuth2:APIアクセスを委譲するための認可フレームワーク。認証には使えません。
- OIDC:OAuth2に「誰か」を確認する認証レイヤーを追加したもの。現代Webアプリの認証はここが基点です。
「OAuth2でログインしている」という表現は厳密には誤りで、「OIDCでログインし、OAuth2でリソースアクセスを委譲している」が正確です。この区別が、設計ミスやセキュリティリスクを避けるための第一歩になります。
参考
- OASIS SAML 2.0 Standard — OASIS Open
- RFC 6749: The OAuth 2.0 Authorization Framework — IETF
- RFC 7636: PKCE — IETF
- OpenID Connect Core 1.0 — OpenID Foundation
- How OpenID Connect Works — OpenID Foundation
Discussion