SAML と OIDC のどちらを使うかは、シングルサインオンを支えるプロトコルの選択です。SAML 2.0(OASIS 標準、2005年3月)では、ID プロバイダーがユーザーに関する XML アサーションに署名し、ブラウザーがそれをサービスプロバイダーに届けます。OpenID Connect(Core 1.0、2014年2月。ISO/IEC 26131:2024 としても標準化)は、OAuth 2.0 にアイデンティティレイヤーを追加します。プロバイダーは通常、認可コードフローを通じて、署名付きの JWT である ID トークンを発行し、同じやり取りの中で API 用のアクセストークンも発行できます。
比較表
| SAML 2.0 | OpenID Connect | |
|---|---|---|
| 公開 | OASIS 標準、2005年3月 | Core 1.0、2014年2月(2023年に正誤表)。ISO/IEC 26131:2024 |
| トークン | XML アサーション | JWT の ID トークン。加えて OAuth のアクセストークンとリフレッシュトークン |
| 署名 | 正規化を伴う XML 署名。通常は RSA-SHA256 | JWS。RS256 のサポートが必須で、ES256 なども一般的 |
| 転送 | ブラウザーによる POST またはリダイレクト。SOAP によるアーティファクト解決 | リダイレクトで認可コード、トークンはトークンエンドポイントから |
| 設定 | パートナーごとに交換する XML メタデータ | .well-known の URL で公開されるディスカバリドキュメントと JWKS |
| Microsoft Entra ID での実測値(下記を参照) | メタデータ 28〜32 KB、証明書 5 枚 | ディスカバリ 1,728 バイト、RSA 鍵 7 個の JWKS |
| 鍵のローテーション | メタデータに新しい証明書を掲載。多くの場合、各パートナーが手動で更新 | 自動:クライアントが JWKS を再取得 |
| ネイティブアプリとモバイルアプリ | 扱いにくい(サーバーへのブラウザー POST) | 想定して設計されている(RFC 8252、PKCE) |
| API へのアクセス | 対象外(別途トークン交換が必要) | 同じフローでアクセストークンを取得 |
| ログアウト | フロントチャネルまたはバックチャネルによるシングルログアウト | RP 起点、フロントチャネル、バックチャネルの各ログアウト(2022年に最終版) |
| 主な利用者 | 企業向け SaaS、大学(eduGAIN)、行政 | 一般消費者向けのログイン、最新の SaaS、モバイル、従業員の ID 管理 |
それぞれのログインの流れ
SAML では、サービスプロバイダーが AuthnRequest を付けてブラウザーを ID プロバイダーにリダイレクトします。ログイン後、IdP は HTML フォームを返し、このフォームがアサーションを含む base64 エンコードされた Response を POST します。アサーションに含まれるのは、発行者、サブジェクト、オーディエンス制限、有効期間、属性、XML 署名です。サービスプロバイダーは、IdP のメタデータにある証明書で署名を検証し、条件を確認します。
OpenID Connect では、クライアントが scope=openid、state、nonce、PKCE のチャレンジを付けて、プロバイダーの認可エンドポイントにリダイレクトします。プロバイダーはリダイレクト URI に使い捨てのコードを返し、クライアントはそのコードをトークンエンドポイントで、直接の TLS 接続を通じて ID トークンとアクセストークンに交換します。そのため、トークンがブラウザーのアドレスバーを通ることはありません。
以下のスクリプトは、同じプロバイダーから両方の種類の設定を読み込みます(2026年10月20日、curl と jq 1.8.1 を使用)。繰り返し取得すると、応答するサーバーが変わるため、SAML メタデータのサイズは 28〜32 KB、JWKS の鍵の数は 7〜8 個の間で変動しました。
#!/bin/sh
base=https://login.microsoftonline.com/common
echo "== OpenID Connect discovery"
curl -s "$base/v2.0/.well-known/openid-configuration" -o oidc.json
echo "bytes: $(wc -c < oidc.json | tr -d ' ')"
jq -c '{id_token_signing_alg_values_supported, response_types_supported}' oidc.json
curl -s "$(jq -r .jwks_uri oidc.json)" | jq -c '{jwks_keys: (.keys | length), kty: ([.keys[].kty] | unique)}'
echo "== SAML 2.0 metadata"
curl -s "$base/FederationMetadata/2007-06/FederationMetadata.xml" -o saml.xml
echo "bytes: $(wc -c < saml.xml | tr -d ' ')"
grep -o 'SignatureMethod Algorithm="[^"]*"' saml.xml | sort -u
grep -o 'SingleSignOnService Binding="[^"]*"' saml.xml | sort -u
echo "distinct certificates: $(grep -o '<X509Certificate>[^<]*' saml.xml | sort -u | wc -l | tr -d ' ')"
rm -f oidc.json saml.xml
== OpenID Connect discovery
bytes: 1728
{"id_token_signing_alg_values_supported":["RS256"],"response_types_supported":["code","id_token","code id_token","id_token token"]}
{"jwks_keys":7,"kty":["RSA"]}
== SAML 2.0 metadata
bytes: 28179
SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
distinct certificates: 5
リライングパーティが必ず確認すべき項目
SAML:XML 署名は、自分で設定した IdP の証明書で検証し(メッセージに埋め込まれた証明書は決して使わないでください)、コードが読み取るアサーションそのものが署名の対象になっていることを確かめます。そのうえで Issuer、Destination、InResponseTo、AudienceRestriction、NotBefore、NotOnOrAfter を確認し、リプレイを拒否します。難しさは構造に起因します。XML 署名は、正規化の後に ID で参照される要素に署名するため、1 つの文書の中に、正しく署名された要素と、アプリケーションが代わりに処理する別の未署名の要素とが同居し得ます。2012年に Somorovsky らは、SAML フレームワーク 14 個のうち 11 個でこのような署名ラッピングが成立することを示しました。2024年と 2025年には、同じライブラリ内の 2 つの XML パーサーが 1 つの文書を異なる形で解釈していたために、ruby-saml(GitLab が使用)が再び修正を必要としました(CVE-2024-45409、CVE-2025-25291、CVE-2025-25292)。
OpenID Connect(Core §3.1.3.7):kid で照合したプロバイダーの JWKS の鍵と、想定どおりのアルゴリズムで JWS を検証します。そのうえで iss、aud(自身のクライアント ID)、exp、iat、送信した nonce を確認します。JSON の構文木は 1 通りしかなく、署名は受信したバイト列そのものを対象とするため、ラッピングの問題は起きません。残る落とし穴は、想定外のアルゴリズムの受け入れ、aud の確認の省略、緩いリダイレクト URI の照合で、OAuth のセキュリティに関するベストカレントプラクティス(RFC 9700、2025年1月)がこれらに対処しています。OIDC ID トークンバリデーターはプロバイダーの実際の JWKS に対してこれらのチェックを実行し、SAML インスペクターは署名が実際にどの要素を対象としているかを表示します。
どちらを選ぶべきか
- 新しいアプリケーション、モバイルアプリ、シングルページアプリ、API:コードフローと PKCE を使った OpenID Connect を使います。
- 企業向けに SaaS を販売する場合:両方をサポートします。多くの顧客企業の ID 管理チームは、今でもまず SAML を設定します。
- 研究・教育機関のフェデレーション(eduGAIN、InCommon):メタデータアグリゲートとともに SAML を使います。OpenID Federation 1.0(2026年2月に最終版)は eduGAIN で試験導入が進められていますが、まだ一般的ではありません。
- 行政と規制業種:所属するエコシステムが義務付けるプロファイルに従います。オープンバンキングや同様の制度では、OAuth と OpenID Connect を強化したプロファイルである FAPI 2.0 が使われています。
- ユーザーとグループのプロビジョニング:どちらも該当しません。いずれのプロトコルとも併用できる SCIM 2.0(RFC 7643 と RFC 7644)を使います。
移行時の注意点
- 両方を並行して運用する:切り替える前に、同じ ID プロバイダーに OIDC アプリケーションを設定し、同じユーザー識別子(
subまたは変化しない属性)を既存のアカウントに対応付けます。 - 属性からクレームへの対応付けは明示的に行います。SAML の属性名(多くの場合は URN)が OIDC のクレーム名と一致することはまれで、ユーザーが多数のグループに所属している場合、グループのクレームには別途 API 呼び出しが必要になることがあります。
- OpenID Connect には認定済みのライブラリを使い、ディスカバリと JWKS のキャッシュを有効にして未知の
kidを受け取ったら再取得するようにし、受け入れるアルゴリズムを固定します。 - SAML に残すものを堅牢にする:ライブラリを更新し、署名付きアサーションを必須にし、複数のアサーションや DTD を含む文書を拒否し、パートナーのメタデータにある証明書の有効期限を監視します。
- ログアウトは別途計画する:セッションを一元的に終了させる必要がある場合は、SAML のシングルログアウトを OIDC のバックチャネルログアウトに対応付けます。
- SAML 接続の廃止は、1 つの業務サイクル全体を通じて SAML でのログインがないことをログで確認してから行います。
参考資料
- OASIS SAML 2.0 Core とバインディング仕様
- OpenID Connect Core 1.0(§3.1.3.7 ID トークンの検証)
- OpenID Connect Discovery 1.0
- OpenID Connect Back-Channel Logout 1.0
- RFC 9700:OAuth 2.0 セキュリティのベストカレントプラクティス
- RFC 7636:PKCE と RFC 8252:ネイティブアプリ向けの OAuth
- W3C:XML 署名の構文と処理 1.1
- Somorovsky ほか「On Breaking SAML」、USENIX Security 2012