SAML
企業の ID プロバイダーとサービスプロバイダー間でシングルサインオンを実現する XML ベースの認証プロトコル
SAML とは
SAML (Security Assertion Markup Language) は、ID プロバイダー (IdP) とサービスプロバイダー (SP) の間で認証・認可情報を XML 形式で交換するプロトコルである。SAML 2.0 は 2005 年 3 月に OASIS 標準として承認され、後に ITU-T 勧告 X.1141 としても採択された。2026 年 8 月時点でも、社内の ID 基盤と業務用 SaaS を結ぶ企業向けの SSO では広く使われている。仕組みの要点は、SP が自前でパスワードを持たず、IdP が署名した「この人は確かに認証した」という主張 (Assertion) を受け取って信用する点にある。多要素認証の強制やアカウントの停止を IdP 側だけで完結させられるのは、この構造の帰結である。
認証フロー
SSO の開始点は 2 通りある。ユーザーが業務アプリの URL を直接開いたときに始まるのが SP 起点 (SP-Initiated) で、SP は未認証のアクセスを受けて AuthnRequest を作り、ブラウザ経由で IdP へ送る。HTTP Redirect バインディングではこの要求を DEFLATE で圧縮して URL のクエリに載せるため、元々開こうとしていた画面の情報は要求本体ではなく RelayState に預け、認証後にそこへ戻す。
1. ユーザーが SP (例: Slack) にアクセス
2. SP が SAML AuthnRequest を生成し、IdP にリダイレクト
3. ユーザーが IdP (例: Okta) でログイン
4. IdP が SAML Response (Assertion) を生成
5. ブラウザが SAML Response を SP に POST
6. SP が Assertion を検証し、ログイン完了
[ユーザー] → [SP: Slack] → リダイレクト → [IdP: Okta]
↓ ログイン
[ユーザー] ← [SP: Slack] ← POST Assertion ← [IdP: Okta]
もう 1 つは IdP 起点 (IdP-Initiated) で、ユーザーが IdP のポータルに並んだアプリのリンクを押して始まる。この経路では SP からの AuthnRequest が存在せず、IdP が Assertion を作って SP の Assertion Consumer Service へ直接 POST する。あらかじめ IdP 側にアプリごとの遷移リンクを設定しておく必要があり、SP から見れば頼んでいない Response が届く形になるため、検証は SP 起点より慎重に行う必要がある。どちらの経路に対応するかは SaaS 側の実装で決まっており、片方しか使えない製品もある。
SAML Assertion の構造
Assertion は「誰が」「いつまで」「どこ向けに」認証されたかを入れ子の XML で表す。SP が検証しなければならない項目は、この構造の中に散らばっている。
<saml:Assertion>
<saml:Issuer>https://idp.example.com</saml:Issuer>
<saml:Subject>
<saml:NameID>user@example.com</saml:NameID>
</saml:Subject>
<saml:Conditions NotBefore="..." NotOnOrAfter="...">
<saml:AudienceRestriction>
<saml:Audience>https://sp.example.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AttributeStatement>
<saml:Attribute Name="role">
<saml:AttributeValue>admin</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
改ざんの防止は XML 署名で行い、SP は事前に交換した IdP のメタデータに含まれる公開鍵で署名を検証する。ただし署名が通っただけでは足りない。実装で漏れやすいのは次の 4 点である。
ConditionsのNotBefore/NotOnOrAfter: 有効期間を外れた Assertion を拒否する。IdP と SP の時計がずれていると正当な Assertion まで弾かれるため、許容するずれは小さく取り、両者の時刻同期を前提条件として扱う。AudienceRestriction: 自分宛ての Assertion かを確かめる。ここを見ないと、別の SP 向けに発行されたものをそのまま受け入れてしまう。InResponseToと再利用の拒否: SP 起点では自分が出した AuthnRequest の ID と対応しているかを照合し、一度使った Assertion の ID を記録して使い回しを断る。- 署名の対象: 署名は Response 全体に付く場合と Assertion に付く場合がある。「どこかに署名がある」ではなく「自分が信用しようとしているデータそのものが署名対象か」を確認する。
最後の項目は理屈上の注意ではない。XML 署名は署名対象を参照で指す仕様のため、署名済みの要素を文書内の別の場所へ移し、参照されない位置に偽の要素を差し込む XML 署名ラッピングという攻撃が成立し得る。2012 年の USENIX Security で発表された調査では、対象とした主要な SAML 実装 14 種のうち 11 種にこの種の欠陥が見つかっている。署名検証を自作せず、保守が続いているライブラリに任せるべき理由がここにある。
OIDC との比較
両者は新旧の関係というより、想定していた利用者が違う。SAML はブラウザと企業の ID 基盤を前提に設計され、OIDC はモバイルアプリや SPA を含む前提で作られている。
| 観点 | SAML 2.0 | OpenID Connect |
|---|---|---|
| データ形式 | XML | JSON / JWT |
| 用途 | エンタープライズ SSO | Web / モバイルアプリ |
| 実装の複雑さ | 高い (XML 署名、パース) | 低い (JSON、JWT) |
| モバイル対応 | 不向き | 適している |
新規に選べるなら、ライブラリが揃っている OIDC の方が実装は軽い。SAML を選ぶのは、社内の ID 基盤や連携先の SaaS が SAML しか話せない場合である。両方を話せる IdP を挟み、社内は SAML・自社アプリは OIDC と変換する構成もとれる。既存の SAML 連携をわざわざ置き換える利点は薄いので、新しく増える分から OIDC に寄せるのが現実的な進め方になる。
AWS での SAML 連携
- IAM Identity Center: 外部の SAML IdP を ID ソースにして、複数の AWS アカウントとロールへのアクセスをまとめて払い出す
- Cognito User Pool: SAML IdP をフェデレーション ID プロバイダーとして設定し、自社アプリケーションのログインに使う
- IAM SAML プロバイダー: IdP のメタデータを登録し、
AssumeRoleWithSAMLで Assertion を一時的な AWS 認証情報に交換する
AssumeRoleWithSAML の呼び出しには AWS の認証情報が不要で、呼び出し元の正当性は登録済みメタデータの鍵で検証される。セッションは既定で 1 時間、DurationSeconds には 900 秒からそのロールの最大セッション時間 (1 時間から 12 時間の範囲で設定) までを指定できるが、Assertion の SessionNotOnOrAfter が先に来る場合はそちらで打ち切られる。なお IAM Identity Center が管理するロール (名前が AWSReservedSSO_ で始まるもの) に対してこの API は使えないため、Identity Center 経由の SSO と自前の SAML 連携は別の道具として設計する。
SAML 連携で実際に詰まる場所は毎回よく似ている。IdP の署名証明書の期限切れ、IdP と SP の時刻ずれ、そして Assertion の宛先違いである。証明書には有効期限があり、更新手順と期限の監視を連携を組んだ時点で決めておかないと、ある朝いきなり全員がログインできなくなる。
この記事は役に立ちましたか?
関連用語
シングルサインオン
1 回の認証で複数のアプリケーションやサービスにアクセスできる仕組み
OpenID Connect
OAuth 2.0 の上に構築された認証レイヤーで、ユーザーの身元情報を ID トークンとして提供する
OAuth 2.0
ユーザーのパスワードを渡さずに、リソースへの限定的なアクセスを許可する認可フレームワーク
Passkey
パスワード不要の認証技術で、FIDO2/WebAuthn 標準に基づく
Amazon Cognito
Web / モバイルアプリに認証 / 認可機能を追加する AWS マネージドサービス
相関 ID
分散システムで 1 つのリクエストに紐づく全ログを追跡するための一意な識別子