11 人が閲覧(直近 30 日) セキュリティ

SAMLとは?認証フロー・IdP/SPの仕組みとOAuth・OIDCとの使い分けを実装視点で解説

SAMLとは?認証フロー・IdP/SPの仕組みとOAuth・OIDCとの使い分けを実装視点で解説

SAML(Security Assertion Markup Language)は、IdP(IDプロバイダ)とSP(サービスプロバイダ)の間でXML形式の認証情報をやり取りし、シングルサインオン(SSO)を実現する標準規格です。SSOそのものの定義と、SAML以外を含む4つの実現方式はシングルサインオン(SSO)とは?4つの実現方式と実装・IdP選定で整理しています。この記事では、SAML 2.0のアサーション構造、SP-Initiated/IdP-Initiatedの認証フロー、バインディング、署名と有効期限の検証、OAuth 2.0・OIDCとの使い分けを、設計判断できる粒度で扱います。python3-samlでSPを組みACSでSAMLResponseを検証する動くコードも掲載しました。社内IdPを自社サービスへ連携させる担当者や、SAML対応を製品に組み込む開発者が対象です。

まとめ:SAMLはXMLアサーションで認証を運ぶSSO標準と実装の要点

SAMLは、認証を担うIdPが署名付きのXMLアサーションを発行し、SPがその署名を検証してログインを成立させるプロトコルです。現行の主流はSAML 2.0で、仕様書Assertions and Protocols for the OASIS SAML V2.0の表紙に「OASIS Standard, 15 March 2005」とあります。企業SSOの中心はWeb Browser SSO Profileで、SPが起点となるSP-Initiatedが基本形。IdPポータルから起動するIdP-Initiatedは経路が短い反面、リプレイやCSRFへの備えを自前で設計します。

選定の勘所は責務の切り分けです。SAMLは認証と属性連携をXMLで運び、OAuth 2.0は権限の委譲(認可)、OIDCはOAuth 2.0の上にJWTで認証層を足したもの。新規のSPAやモバイルならOIDC、社内IdPがSAML前提ならSAMLを選びます。実装では署名検証・有効期限・オーディエンス制限の3点を外すと、なりすましの穴になります。

SAMLの基本構造とIdP・SP・アサーションが担う認証の役割分担

SAMLを理解する近道は、登場する3者と、その間で渡される「アサーション」というXML文書の役割を押さえることです。中身は複雑でも、信頼の流れ自体は単純な構図。

IdP・SP・プリンシパルの3者とメタデータ交換で結ぶ信頼関係

SAMLには3つの登場人物がいます。認証情報を管理し身元を保証するIdP(Identity Provider)、機能を提供するSP(Service Provider)、両者を利用する本人であるプリンシパル(ユーザー)です。SPは自前でパスワードを持たず、「確かに本人だ」という判断をIdPに委ねます。

この委任が成り立つ前提が、IdPとSPの事前の信頼関係になります。両者はentityIDと署名用の公開鍵証明書を含むメタデータXMLを交換し、相手を識別できる状態を先に作ります。交換する要素はSAML V2.0 Metadata仕様が定義し、entityID・AssertionConsumerService・KeyDescriptorが最小の構成。信頼を結んでいないIdPのアサーションをSPが受け付けない点が、SAMLの安全性の土台です。信頼をどう結び契約終了時にどう解くかはフェデレーション認証のIdPとSPの信頼設計と属性連携、ユーザー原本が社内ディレクトリにある構成はLDAPとディレクトリサービスの仕組みにまとめました。

SAMLアサーションの3種類と署名・宛先・有効期限で守る中身

アサーションはIdPが発行するXML文書で、SPに渡す「保証書」にあたります。仕様上は3種類。ログインの事実を伝える認証アサーション、氏名や部署・権限を伝える属性アサーション、リソースへのアクセス可否を伝える認可決定アサーションで、企業SSOの中心は前の2つです。

アサーションにはXML Signatureによる電子署名が付き、SPは署名を検証して改ざんの有無を確かめます。署名の構文と処理そのものはW3CのXML Signature Syntax and Processing 1.1が定め、SAMLはそれを参照する形。加えて宛先を縛るAudience制限、受信者を指定するRecipient、有効期限を示すNotOnOrAfterが含まれます。ここを検証しないと、別SP向けのアサーションを使い回されかねません。ユーザーの識別子はNameID要素に入り、永続IDやメールアドレス形式から要件に合わせて選びます。

SAMLResponseのXMLを開いて検証対象の要素を確かめる

設定画面の項目名だけを追っていると、どの値が何を守るのかが見えません。IdPから届くSAMLResponseは、Base64をデコードすれば人が読めるXMLです。骨格を抜き出すと次のようになります。

<samlp:Response ID="_r001" Version="2.0"
    Destination="https://sp.example.jp/acs" InResponseTo="_a1b2c3">
  <saml:Issuer>https://idp.example.jp/metadata</saml:Issuer>
  <ds:Signature> ... </ds:Signature>
  <saml:Assertion ID="_a001" IssueInstant="2026-09-06T02:00:00Z">
    <saml:Subject>
      <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
        u-4821
      </saml:NameID>
      <saml:SubjectConfirmationData NotOnOrAfter="2026-09-06T02:05:00Z"
          Recipient="https://sp.example.jp/acs" InResponseTo="_a1b2c3" />
    </saml:Subject>
    <saml:Conditions NotBefore="2026-09-06T01:59:00Z"
                     NotOnOrAfter="2026-09-06T02:09:00Z">
      <saml:AudienceRestriction>
        <saml:Audience>https://sp.example.jp/metadata</saml:Audience>
      </saml:AudienceRestriction>
    </saml:Conditions>
    <saml:AttributeStatement> ... </saml:AttributeStatement>
  </saml:Assertion>
</samlp:Response>

SPが検証すべき値は、この抜粋にすべて現れています。DestinationとRecipientが自分のACSを指すか、InResponseToが送信したSAMLRequestのIDと一致するか、NotBefore/NotOnOrAfterが現在時刻を挟むか、Audienceが自SPのentityIDと一致するか。この4点にds:Signatureの妥当性を足せば、Web Browser SSO Profileが求める検証を満たせます。

SAML認証フローの実装:SP-InitiatedとIdP-Initiatedの経路差

SAMLの認証フローは、どちらが起点になるかで2系統に分かれます。この経路差と、ブラウザ経由での受け渡し方法(バインディング)の選択が、そのまま設計判断になります。

SP-Initiated SSOのリダイレクトから戻りまでの5工程

もっとも使われるのがSP-Initiated方式です。ユーザーが未ログインでSPにアクセスすると、SPはSAMLRequestを生成してブラウザをIdPへリダイレクトさせます。IdPは本人確認を行い、署名付きのSAMLResponseをブラウザ経由でSPへ戻す仕組み。SPは署名と条件を検証し、セッションを張ります。処理の順序は次のとおりです。

  • ユーザーがSPの保護されたページへアクセスする
  • SPが認証要求を作りブラウザをIdPへ転送する
  • IdPがログイン画面で本人を認証する
  • IdPが署名付きレスポンスをSPへ返す
  • SPが署名を検証しセッションを確立する

この方式はSP側でアクセス先が確定しているため、ログイン後に本来行きたかったページへ戻す制御を組みやすい特性があります。要求と応答の中身をIdP側の記述で確かめたいときは、Microsoftが公開するEntra IDのSAMLプロトコル仕様が読みやすい対照。SAMLRequestと返却されるSAMLResponseの要素名が並べて示されています。

IdP-Initiated方式との経路差とリプレイ対策の注意点

IdP-Initiated方式では、ユーザーが先にIdPのポータルにログインし、そこに並ぶアプリのアイコンからSPへ飛びます。IdPはSPからの要求を待たずにアサーションを送り込むため、経路は短くなる構造。一方でSPは「頼んでいないログイン」を受け取る形になり、SAMLRequestと突き合わせた検証ができません。

この非対称さがリスクの温床です。盗まれたアサーションの再送や意図しないSPへのログイン誘発があるため、許可するなら一意ID(ID属性)の使い回し検知と短い有効期限が前提。社内ポータルの導線を優先する場面を除けば、まずSP-Initiatedを基本に据える設計をおすすめします。python3-samlならrejectUnsolicitedResponsesWithInResponseToを真にして、InResponseToを持たない応答を拒否できます。

HTTP-Redirect・HTTP-POSTバインディングとメタデータ交換

SAMLメッセージをブラウザで運ぶ手段を「バインディング」と呼びます。実装で使うのは主に2つ。往路にはURLへ載せるHTTP-Redirect、復路にはフォーム自動送信のHTTP-POSTという組み合わせが定番です。符号化方法や署名の載せ方はSAML V2.0 Bindings仕様に規定があります。

バインディング 運び方 主な用途
HTTP-Redirect URLパラメータ 認証要求の送信
HTTP-POST フォーム自動送信 署名付き応答の返却
HTTP-Artifact 参照IDで後取得 大きな応答の受渡

復路にHTTP-POSTを使うのは、署名付きレスポンスがURL長の制限を超えやすいためです。SPが応答を受け取るエンドポイントはメタデータ内のAssertion Consumer Service(ACS)として宣言し、IdPはそこにだけ返します。証明書更新時も同じ仕組みで鍵を切り替えます。

python3-samlでSPを実装しACSで署名を検証する手順

ここからは手を動かす章です。SP側を1つ組むと、設定項目と仕様の対応が短時間で腑に落ちます。Python向けのツールキットで、設定・検証・メタデータ生成の3工程を通します。

python3-samlを入れてsettings.jsonに証明書を設定する

SP実装の土台にはSAML-Toolkits/python3-samlを使います。PyPIでの最新は1.16.0(2023年10月公開・2026年9月時点)で、導入はpip install python3-samlの1行。XML署名にxmlsecを使うため、libxml2とxmlsec1の開発パッケージも先に入れます。設定はsettings.jsonとadvanced_settings.jsonの2ファイルです。

# saml/settings.json(SPとIdPの接続先と鍵を宣言する)
{
  "strict": true,
  "debug": false,
  "sp": {
    "entityId": "https://sp.example.jp/metadata",
    "assertionConsumerService": {
      "url": "https://sp.example.jp/acs",
      "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
    },
    "singleLogoutService": {
      "url": "https://sp.example.jp/slo",
      "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
    },
    "x509cert": "MIICxxxx...",
    "privateKey": "MIIExxxx..."
  },
  "idp": {
    "entityId": "https://idp.example.jp/metadata",
    "singleSignOnService": {
      "url": "https://idp.example.jp/sso",
      "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
    },
    "x509cert": "MIICyyyy..."
  }
}

strictを真にすることが実務上の前提。偽のままだと有効期限やAudienceの不一致を警告どまりで通し、検証の意味が消えます。advanced_settings.jsonのsecurityブロックでは、署名要求と受理条件を明示します。

# saml/advanced_settings.json の security ブロック(抜粋)
"security": {
  "wantAssertionsSigned": true,
  "wantMessagesSigned": true,
  "wantAssertionsEncrypted": false,
  "rejectUnsolicitedResponsesWithInResponseTo": true,
  "signatureAlgorithm":
    "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
  "digestAlgorithm": "http://www.w3.org/2001/04/xmlenc#sha256"
}

ACSでSAMLResponseを検証しセッションを確立するコード

次にACSエンドポイントを実装します。ライブラリのprocess_responseが署名・有効期限・Audience・InResponseToの検証をまとめて行い、失敗理由はget_last_error_reasonから取れます。ここを自作しないのが実装事故を減らす近道。

# app.py(Flask + python3-saml 1.16系のACS実装)
from flask import Flask, request, session
from onelogin.saml2.auth import OneLogin_Saml2_Auth

app = Flask(__name__)
app.secret_key = 'change-me'

def build_req(req):
    return {
        'https': 'on',
        'http_host': req.host,
        'script_name': req.path,
        'get_data': req.args.copy(),
        'post_data': req.form.copy(),
    }

@app.route('/acs', methods=['POST'])
def acs():
    auth = OneLogin_Saml2_Auth(build_req(request),
                               custom_base_path='./saml')
    auth.process_response()
    errors = auth.get_errors()
    if errors or not auth.is_authenticated():
        # 検証の失敗理由は必ずログへ。画面には詳細を出さない
        app.logger.warning('SAML NG: %s %s', errors,
                           auth.get_last_error_reason())
        return 'authentication failed', 401
    session['name_id'] = auth.get_nameid()
    session['attrs'] = auth.get_attributes()
    return 'login ok', 200

わざと失敗させる試験も通しておきます。idp側x509certを1文字書き換えれば署名検証で落ち、Audienceを別のentityIDに変えれば宛先違いで落ちる挙動。どちらも401になり、ログにSignature validationやAudienceの不一致が出ます。落ちないならstrictが偽のままか、IdPが署名なしで送っている疑いが濃厚。セッションの保存先選定はセッション管理とセッションIDの発行から失効までの実装に整理しました。

SPメタデータXMLを生成してIdPへ登録し疎通確認まで進める

最後にSP側のメタデータXMLを書き出し、IdPへ登録します。手書きせず生成させるのは、entityIDとACSのURL、証明書の3点を取り違えると疎通しないためです。妥当性検査も同時に回せます。

# SPメタデータを標準出力へ書き出す
python -c "from onelogin.saml2.settings import OneLogin_Saml2_Settings as S; s = S(custom_base_path='./saml', sp_validation_only=True); print(s.get_sp_metadata().decode())"

# 生成したメタデータを検査する(空リストなら合格)
python -c "from onelogin.saml2.settings import OneLogin_Saml2_Settings as S; s = S(custom_base_path='./saml', sp_validation_only=True); print(s.validate_metadata(s.get_sp_metadata()))"

出力されたXMLをIdPの管理画面へアップロードすると、entityIDとACSが自動で読み込まれます。疎通で最初につまずくのはURLの表記ゆれで、末尾のスラッシュ有無やhttpとhttpsの差がほとんど。IdP側のログにAudience mismatchやDestinationの不一致が出ていれば、そこを照合します。JavaやKotlinならSpring SecurityのSAML 2.0サービスプロバイダ機能が同じ役割を担い、SaaS相手の実例はGitHub SSOの設定手順とSAML連携の落とし穴にまとめました。

SAMLとOAuth 2.0・OIDCの違いを認証と認可の境界で使い分け

SAMLの設計判断で必ず突き当たるのが、OAuth 2.0・OIDCとの棲み分けです。3者は似た文脈で語られますが、担う責務が別。取り違えると、認可の仕組みで認証を代用する設計ミスにつながります。

SAML・OAuth 2.0・OIDCの責務とデータ形式の比較

3者の違いは「何を運ぶか」で整理できます。SAMLは認証と属性をXMLで運ぶ規格、OAuth 2.0は権限の委譲を担う認可の枠組みで、仕様はRFC 6749 The OAuth 2.0 Authorization Framework(2012年10月)。OIDCはその上に載せた認証層でJWTを使います。JWTの構造や署名検証はJWTとは?構造・署名検証の仕組みとセッション・OAuth/OIDCとの違いを参照してください。OAuth 2.0単体は「誰か」を保証しないため、ログイン用途への流用は本人性の担保が弱くなります。

規格 主な責務 データ形式 登場時期
SAML 2.0 認証と属性連携 XML 2005年3月
OAuth 2.0 認可(権限委譲) トークン 2012年10月
OIDC 認証層の追加 JWT 2014年2月

二者択一とは限りません。既存のSAML基盤で認証を済ませ、その先のAPI呼び出しにOAuthのアクセストークンが要る構成では、RFC 7522(2015年5月)がSAML 2.0 Bearer Assertionをトークン要求の材料に使う手順を定義。個別の仕組みはOAuth 2.0とは?仕組み・認可フローと認証・認可の違いとOIDC(OpenID Connect)とは?仕組み・OAuthとの違いで扱っています。

SPA・モバイルと既存業務システムでプロトコルを選ぶ判断基準

選定は玉虫色にせず、条件で言い切れます。フロントとAPIが分離したSPAやスマートフォンアプリを新規に作るなら、JWTが軽く運用情報も豊富なOIDCが扱いやすい選択。XMLの署名処理とリダイレクトを多用するSAMLは、この構成では実装コストが重くなります。

逆に、接続先の社内IdP(Active Directoryフェデレーションや既存のSSO基盤)がSAMLしか話せない場合や、SaaS側がSAML接続だけを提供している場合は、素直にSAMLを選びます。ここでOIDCに寄せると、追加のブリッジを自作する羽目になり費用対効果が崩れる展開。両方を1つの基盤で受けたいなら、SAMLとOIDCを併せて話せるIDaaSとSSO・IdPの違いとSAML・OIDC・SCIM連携を土台に据える手もあります。

SAML導入時の署名検証・シングルログアウト・採用可否の判断基準

SAMLは仕様が広く、実装の抜けがセキュリティ事故に直結します。押さえるべき検証項目と、採用を見送るべき場面を示します。SSOを組み込む設計段階での判断材料です。

署名・有効期限・Audience検証で外してはいけない4項目

SPの実装で最初に固めるのが検証ロジックです。署名検証を省いたり、署名アルゴリズムの検証を緩めたりすると、偽造アサーションを受け入れる穴になります。最低限外せない検証は次の項目。有無ではなく値まで突き合わせます。

  • IdP証明書によるXML署名の妥当性
  • NotBeforeとNotOnOrAfterの有効期限
  • 自SPを指すAudience制限の一致
  • アサーションIDの一意性(再送検知)

これらは自作せず、実績あるSAMLライブラリに任せる判断が堅実です。前章のwantAssertionsSignedとstrictを真にしておけば、4項目のうち3つは機械的に効きます。残るアサーションIDの一意性だけは、使用済みIDを一定期間保持する仕組みをSP側で用意します。

XML Signature Wrapping攻撃を防ぐ検証実装の順序

SAMLで繰り返し問題になってきたのがXML Signature Wrapping(XSW)です。攻撃者は正規の署名付きアサーションを保持したまま、署名対象ではない位置に偽のアサーションを差し込みます。署名検証は「正しい署名がある」と判定し、その後アプリ側が別の要素を読むと、なりすましが成立する筋道。原因は暗号の弱さではなく、署名した要素と実際に読む要素がずれる実装差です。

防ぎ方は手順の固定です。署名を検証したうえで、参照されたID属性が指す要素そのものをアプリ側が読む、という順序を崩さないこと。getElementsByTagNameで先頭のアサーションを拾う書き方は避けます。OASISもこのリスクをSAML V2.0のセキュリティおよびプライバシー考慮事項で整理しており、自作パーサを避けてライブラリを最新版に追随させる運用が現実的な防御線。

シングルログアウト(SLO)とセッション有効期限の設計上の判断

ログインの裏返しとして設計が要るのがシングルログアウト(SLO)です。SAMLにはSPまたはIdPからログアウトを開始し、連携する全SPのセッションを一括で終わらせる仕組みがあります。ただし全SPが正しく応答する前提のため、1つが無応答なだけで全体が中途半端になりがち。

そのため、SLOを厳密に実装するか、各SPのセッション有効期限を短めにして自然失効へ寄せるかは、扱う情報の機微さで判断します。即時失効が要る金融や医療はSLOを作り込み、社内ツール中心なら短命セッションで運用を軽くする切り分けが現実的。SP側の寿命はIdPのアサーション有効期限と整合させます。

SAMLを採用すべき場面と見送るべき場面の条件付きの切り分け

SAMLを採用する判断は、既存環境で決まります。接続先がActive Directoryフェデレーションや主要IDaaSのSAMLコネクタで、社内アプリへの一括ログインを束ねたいなら実績のある選択。多数のSaaSがSAML接続を標準提供している点も後押しになります。

逆に、これから作るのがモバイル主体のサービスで接続先IdPもOIDCを話せるなら、SAMLは見送ってOIDCに寄せた方が実装は軽く済みます。XMLの署名処理はモバイル環境と相性が悪いためです。「既存IdPがSAML前提かどうか」を最初の分岐に置き、そうでなければOIDCを既定にする方針が遠回りしません。実装後に連携が繋がらない場合の原因切り分けは、SAML NameIDFormatとメタデータの不一致でSSOが失敗する原因の切り分けで扱っています。

SSOで入り口を揃えても、アカウントの作成・停止が手作業なら退職者のIDが残ります。この自動化はSCIMとID自動プロビジョニングの仕組みで扱い、SAML SSOと対で設計すると入退社の運用が回る形。自社の会員基盤や業務システムへのSAML SSO組み込みは、認証基盤・ID管理システム開発として認証連携ごと受託しています。本人確認そのものの底上げは二段階認証とは?二要素認証・多要素認証との違いと企業の導入判断を参照してください。

よくある質問

導入検討でよく挙がる疑問を、実装者の視点でまとめます。

SAMLとSSOは同じ意味ですか?

同じではありません。SSO(シングルサインオン)は1度のログインで複数サービスを使える「仕組みの概念」で、SAMLはそれを実現する「規格の1つ」です。SSOはOIDCやKerberosでも実現でき、SAMLはWebのフェデレーション型SSOで広く使われる実装手段という関係。

SAMLとOAuthはどちらを使うべきですか?

目的で分かれます。ログイン(認証)と属性連携が主目的ならSAMLかOIDC、外部サービスへのAPIアクセス権限を委譲したい(認可)ならOAuth 2.0です。OAuth 2.0単体を認証代わりにするのは本人性の保証が弱く、その用途にはOIDCが向きます。両方が要るならRFC 7522でアサーションをトークンへ交換する経路も選べます。

SAML 2.0と1.1の違いは何ですか?

SAML 2.0は2005年3月15日にOASIS標準として承認された版で、SAML 1.1やShibbolethの仕様を統合し、SP-Initiatedフローやメタデータ交換、SLOを整理したものです。企業SSOやSaaS連携はほぼ2.0が前提で、新規実装で1.1を選ぶ場面は限られます。

SAML実装で最初に確かめるべき設定は何ですか?

ライブラリのstrict相当の設定を真にすることです。python3-samlならsettings.jsonのstrictで、偽だと有効期限やAudienceの不一致を素通しします。wantAssertionsSignedも真にし、署名のないアサーションを受理しない状態にしてから疎通試験へ入ってください。

SAMLの導入に自社開発は必要ですか?

接続する両側の作り込み次第です。市販SaaSと主要IdPの組み合わせなら管理画面の設定だけで済むこともあります。自社製アプリをSPにする場合はメタデータ交換・署名検証・セッション連携の実装が要り、既存ライブラリを土台に組むか、認証連携に慣れた開発会社へ委託する判断になります。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

ほか 8 件の記事からもリンクされています。

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.09 テックブログ IDCFクラウド(IDCフロンティア)不正アクセス・ランサムウェア:影響先・復旧・データは戻るか
  2. 2026.10.08 テックブログ 大阪公立大学のランサムウェア被害と仮想化基盤の停止|全授業休講に至った経緯とバックアップを守る設定
  3. 2024.11.08 テックブログ OpenAPI GeneratorでJavaコードを自動生成する方法|CLI導入からSpring・ライブラリ選択まで
  4. 2026.10.09 テックブログ 京王電鉄のランサムウェア被害とグループ共通基盤:決済・ポイント・予約が止まった範囲と遮断の初動
  5. 2026.10.09 テックブログ ニッスイのサイバー攻撃で日水物流の入出荷停止|委託先クラウド障害に荷主が備える手順

RELATED POSTS 関連記事

目次