LOCKED
ブログ一覧に戻る
SSO・IDaaSLOCKED MSO

SAML 2.0仕様の要点【NameID FormatとBinding方式】

関連トピック: SAML認証の実装ガイド【仕様から設定まで完全解説】

SAML 2.0は、XMLで認証情報を受け渡すための業界標準です。異なる組織やドメインのあいだで「このユーザーは認証済みである」という事実を、改ざんを検知できる形で伝える役目を持ちます。

ここでは実装や連携設定のときに実際に参照することになる部分を、仕様のどこに書かれているかとあわせて整理します。扱うのはAssertionの構造、NameID Formatの種類、Binding方式、署名と暗号化、そしてメタデータ交換です。

SAML 2.0はどんな規格か

SAML 2.0は2005年3月にOASISの標準仕様として承認されました。それ以前はSAML 1.1、Liberty AllianceのID-FF 1.2、Shibboleth 1.3が併存していましたが、SAML 2.0はこの3つを一本に統合したものです。現在の企業向けSSOはここを土台にしています。

認証情報を発行する側をIdP(Identity Provider)、それを受け取ってユーザーをログインさせる側をSP(Service Provider)と呼びます。IdPが署名付きのXML文書を発行し、ブラウザがそれをSPへ運び、SPが署名を検証してセッションを張る。これがSAML 2.0の骨格です。

仕様書は役割ごとに4本に分かれています。確認したい内容がどれに載っているかを知っておくと、調べ物の時間が縮みます。

仕様書扱う内容参照したい場面
Core (saml-core-2.0-os)Assertionの構造、AuthnRequest・Responseの要素、NameID Format、ステータスコード要素や属性の意味を確認する
Bindings (saml-bindings-2.0-os)HTTP-POST・HTTP-Redirectなど転送方式送信方法やエンコードを確認する
Profiles (saml-profiles-2.0-os)Web Browser SSOなど利用パターンごとの必須条件SSOとして成立する条件を確認する
Metadata (saml-metadata-2.0-os)EntityDescriptorなど設定情報の交換形式IdPとSPの設定交換でつまずいたとき
RFPテンプレート(無料)

IDaaS導入RFPテンプレート

IDaaS導入の社内稟議に使えるRFPテンプレート。SSO、MFA、プロビジョニングなどの要件を網羅したフォーマットです。

無料でダウンロード

SAML 2.0の基本構成:Assertion・Protocol・Binding

SAML 2.0は、3つの主要コンポーネントから構成されます。

1. Assertion(アサーション)

AssertionはSAML認証の中核であり、ユーザー認証情報を表現するXML文書です。

<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
  Version="2.0"
  ID="_d71a3a8e9ee6e4fd0b3b1f9c0e8e5c7b"
  IssueInstant="2024-03-06T10:30:00Z">

  <saml:Issuer>https://idp.example.com</saml:Issuer>

  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <!-- XML署名 -->
  </ds:Signature>

  <saml:Subject>
    <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
      user@example.com
    </saml:NameID>
    <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
      <saml:SubjectConfirmationData NotOnOrAfter="2024-03-06T11:30:00Z"
        Recipient="https://sp.example.com/acs"/>
    </saml:SubjectConfirmation>
  </saml:Subject>

  <saml:Conditions NotBefore="2024-03-06T10:25:00Z"
    NotOnOrAfter="2024-03-06T11:30:00Z">
    <saml:AudienceRestriction>
      <saml:Audience>https://sp.example.com</saml:Audience>
    </saml:AudienceRestriction>
  </saml:Conditions>

  <saml:AuthnStatement AuthnInstant="2024-03-06T10:30:00Z"
    SessionIndex="s23bdf1f8e9e2e3c5d4f9a1b2c3d4e5f6">
    <saml:AuthnContext>
      <saml:AuthnContextClassRef>
        urn:oasis:names:tc:SAML:2.0:ac:classes:Password
      </saml:AuthnContextClassRef>
    </saml:AuthnContext>
  </saml:AuthnStatement>

  <saml:AttributeStatement>
    <saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
      <saml:AttributeValue>user@example.com</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="givenName">
      <saml:AttributeValue>太郎</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="sn">
      <saml:AttributeValue>山田</saml:AttributeValue>
    </saml:Attribute>
  </saml:AttributeStatement>
</saml:Assertion>

Assertion内の主要要素:

必須かどうかはスキーマ上の定義ではなくProfileで決まります。以下の「扱い」は、もっとも使われるWeb Browser SSO Profileでの位置づけです。

要素説明Web Browser SSOでの扱い
IssuerIdPのエンティティID必要
Subject認証対象ユーザーの識別子必要
SubjectConfirmationMethod に bearer を指定し、Recipient と NotOnOrAfter で使用範囲を限定する必要
ConditionsAudienceRestriction で受け取るべきSPを限定し、NotBefore / NotOnOrAfter で有効期間を示す必要
AuthnStatement認証時刻・方式(パスワード、多要素認証など)必要
AttributeStatementユーザー属性(メールアドレス、部門など)任意

2. Protocol(プロトコル)

ProtocolはAssertion交換の手順を定義します。

AuthnRequest:SPからIdPへ送信される認証要求

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
  ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd"
  Version="2.0"
  IssueInstant="2024-03-06T10:30:00Z"
  Destination="https://idp.example.com/sso"
  AssertionConsumerServiceURL="https://sp.example.com/acs">

  <saml:Issuer>https://sp.example.com</saml:Issuer>

  <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
    AllowCreate="true"/>
</samlp:AuthnRequest>

Response:IdPからSPへ返信される認証応答

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd"
  Version="2.0"
  IssueInstant="2024-03-06T10:31:00Z"
  Destination="https://sp.example.com/acs"
  InResponseTo="_8e8dc5f69a98cc4c1ff3427e5ce34606fd">

  <saml:Issuer>https://idp.example.com</saml:Issuer>

  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
  </samlp:Status>

  <saml:Assertion>
    <!-- Assertion本体 -->
  </saml:Assertion>
</samlp:Response>

NameID Formatの種類と使い分け

NameIDはAssertionの中でユーザーを指す識別子です。その値をどう解釈するかをFormat属性が示します。IdPが送るFormatとSP側の設定が食い違うと、認証そのものは成功しているのにSPがユーザーを特定できず、ログインに失敗します。連携作業でつまずきやすいのはここです。仕様で定義されているのは8種類なので、先に把握しておくと切り分けが早くなります。

FormatURI値の意味
unspecifiedurn:oasis:names:tc:SAML:1.1:nameid-format:unspecified解釈をIdPとSPの取り決めに委ねる
emailAddressurn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressメールアドレス形式。SaaS連携で最も使われる
X509SubjectNameurn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectNameX.509証明書のサブジェクト名
WindowsDomainQualifiedNameurn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedNameドメイン修飾されたWindowsアカウント名
kerberosurn:oasis:names:tc:SAML:2.0:nameid-format:kerberosKerberosのプリンシパル名
entityurn:oasis:names:tc:SAML:2.0:nameid-format:entitySAMLのエンティティ自体を指す。個人ユーザーには使わない
persistenturn:oasis:names:tc:SAML:2.0:nameid-format:persistentIdPと、SPまたはSPの連合(affiliation)の組み合わせごとに固定される仮名。実際のユーザー名などから推測できない値で生成する
transienturn:oasis:names:tc:SAML:2.0:nameid-format:transientそのセッションだけで有効な一時的な値。256文字以内

persistentとtransientの違いは、SP側でユーザーを継続的に紐づけられるかどうかです。persistentは同じユーザーなら毎回同じ値になるためSP側のアカウントと1対1で対応づけられますが、その値はSPごとに別々に発行されるので、通常は複数のSPが持ち寄って照合しても同一人物だとは分かりません。ただし仕様はSPの連合(affiliation)単位での発行も認めているため、その構成では加盟するSPが同じ識別子を共有し、連合の内側では突き合わせが成立します。名寄せを避けたいなら、ここを確認します。transientは毎回変わります。SPが受け取るのは「認証済みの誰かである」という事実だけです。どちらを選ぶかは運用方針の話になるので、SAML統合ベストプラクティスで規模別の考え方を扱っています。

NameIDPolicyで要求する

SPからIdPへ「この形式で返してほしい」と伝えるのがAuthnRequest内のNameIDPolicy要素です。

<samlp:NameIDPolicy
  Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
  SPNameQualifier="https://sp.example.com"
  AllowCreate="true"/>

Formatに要求する形式のURIを指定し、SPNameQualifierでその識別子をどのSPに向けて発行するかを示します。AllowCreateにtrueを指定すると、まだ識別子が割り当てられていないユーザーに対して新規発行を認めます。IdPが要求に応えられない場合は、後述のInvalidNameIDPolicyが返ります。

IdPが対応している形式は、メタデータのNameIDFormat要素で宣言されています。連携前にここを見ておけば、SP側で選べる形式が確認できます。

Binding方式:HTTP-POSTとHTTP-Redirectの違い

SAMLのメッセージをブラウザ経由でどう運ぶかを定めたものがBindingです。Web Browser SSOで使われるのは、主にHTTP-POSTとHTTP-Redirectの2つです。

観点HTTP-POSTHTTP-Redirect
運び方formのhidden fieldに入れてPOSTURLのクエリパラメータに載せてGET
エンコードbase64DEFLATE圧縮 → base64 → URLエンコード
サイズの制約仕様上の上限はないブラウザとサーバーのURL長の制限を受ける
署名XML署名をメッセージ内に含めるクエリパラメータ SigAlg と Signature で付ける
主な用途Response(Assertionの送信)AuthnRequest

HTTP-POST Binding(Responseの標準的な転送方式)

SPのACS(Assertion Consumer Service)URLへ、POSTリクエストでAssertionを送信します。

<form method="post" action="https://sp.example.com/acs">
  <input type="hidden" name="SAMLResponse"
    value="PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDOYWY6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24i..."/>
  <input type="hidden" name="RelayState" value="https://example.com/page"/>
  <input type="submit" value="Continue"/>
</form>

Assertionはbase64にしてPOST本文で送るため、URL長の制限を受けません。属性が多くても、証明書を含んでいても運べます。Responseの転送にこの方式を使うのはそのためです。通信内容はTLSで保護し、Assertion自体の真正性はXML署名で担保します。

HTTP-Redirect Binding

IdPのSSOエンドポイントへ、GETリクエストでAuthnRequestを送信します。

https://idp.example.com/sso?SAMLRequest=jVDPb%2BMEcwx4jFKr%2Fn5YxIwOAAA&RelayState=somevalue
  &SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256
  &Signature=NyZ3S8T1U2V3W4X5Y6Z7A8B9C0D1E2F3G4H5I6J7K8L9M0N1O2P3Q4R5S6T7U8%3D

メッセージはDEFLATEで圧縮してからbase64とURLエンコードを施し、SAMLRequestまたはSAMLResponseというクエリパラメータに載せます。圧縮するのはURLに収めるためで、それでも上限はブラウザやサーバーのURL長の制限に縛られます。2,000文字程度を目安にし、それを超えそうならHTTP-POSTに切り替えます。

この方式ではXML署名ではなく、SigAlgとSignatureのクエリパラメータでメッセージに署名します。値がアドレスバーとアクセスログに残るため、属性を含むResponseの転送には向きません。AuthnRequestの送信に使うのが一般的です。

XML署名とXML暗号化の実装仕様

XML署名(W3C xmldsig)

AssertionおよびResponseに対して、デジタル署名を施すことで、改ざん検知と発信者認証を実現します。

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
    <ds:Reference URI="#_d71a3a8e9ee6e4fd0b3b1f9c0e8e5c7b">
      <ds:Transforms>
        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      </ds:Transforms>
      <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
      <ds:DigestValue>jFDPb/...=</ds:DigestValue>
    </ds:Reference>
  </ds:SignedInfo>

  <ds:SignatureValue>
    5Xda3xD3M7EzM9pL2Q4R9S8T1U2V3W4X5Y6Z7A8B9C0D1E2F3G4H5I6J7K8L9M0N1O2P3Q4R5S6T7U8=
  </ds:SignatureValue>

  <ds:KeyInfo>
    <ds:X509Data>
      <ds:X509Certificate>
        MIIDXTCCAkWgAwIBAgIJAKHHCgVDRV2dMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAlB...
      </ds:X509Certificate>
    </ds:X509Data>
  </ds:KeyInfo>
</ds:Signature>

署名検証フロー(SPでの処理):

  1. AssertionのIssuerを確認
  2. IdPのメタデータからIdPの公開鍵を取得
  3. SignatureValueを公開鍵で検証
  4. DigestValueがAssertion内容と一致することを確認
  5. 署名が有効な場合のみ、Assertionを受け入れ

XML暗号化

機密属性情報(パスワード、マイナンバーなど)が含まれる場合、XML暗号化によってAssertionを保護します。

<saml:Assertion>
  <!-- 平文の要素 -->
  <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
    Type="http://www.w3.org/2001/04/xmlenc#Element">
    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <xenc:EncryptedKey>
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
        <ds:KeyInfo>
          <ds:X509Data>
            <ds:X509Certificate>
              <!-- SP公開鍵 -->
            </ds:X509Certificate>
          </ds:X509Data>
        </ds:KeyInfo>
        <xenc:CipherData>
          <!-- 暗号化されたセッション鍵 -->
        </xenc:CipherData>
      </xenc:EncryptedKey>
    </ds:KeyInfo>
    <xenc:CipherData>
      <!-- 暗号化されたAttribute -->
    </xenc:CipherData>
  </xenc:EncryptedData>
</saml:Assertion>

SAML Responseの検証とステータスコード

連携がうまくいかないとき、最初に見るのはResponse内のStatusCodeです。Success以外の値は、SPとIdPのどちらを調べればよいかを教えてくれます。トップレベルのStatusCodeは4種類しかありません。

Value意味
urn:oasis:names:tc:SAML:2.0:status:Success要求は正常に処理された
urn:oasis:names:tc:SAML:2.0:status:Requester要求した側(SP)に原因がある
urn:oasis:names:tc:SAML:2.0:status:Responder応答する側(IdP)で処理できなかった
urn:oasis:names:tc:SAML:2.0:status:VersionMismatchSAMLのバージョンが合わない

Requesterが返ったらAuthnRequestの内容とSP側の設定を、ResponderならIdPの認証処理と設定を疑います。原因をもう一段細かく伝える場合は、2階層目のStatusCodeが入れ子で付きます。AuthnFailedならIdPはユーザーを認証できず、InvalidNameIDPolicyなら要求されたNameID Formatに応えられず、RequestDeniedなら要求自体を拒否したという意味になります。IdPは運用上の配慮から詳細を省くこともあるため、2階層目が無いケースもあります。

StatusCodeがSuccessなのにログインできない場合は、SP側の検証のどこで落ちているかを次の順で確認します。大半の失敗はこの5点のどれかに当たります。

  1. 署名が検証できているか(前述の検証フロー)
  2. NotBeforeとNotOnOrAfterの有効期間内か
  3. AudienceRestrictionに自分のエンティティIDが入っているか
  4. InResponseToが送信したAuthnRequestのIDと一致しているか
  5. NameIDのFormatと値がSP側の設定と合っているか

Profile:使用パターン定義

Web Browser SSO Profile

最も一般的なSAML利用シーン:ブラウザでログインが必要な場合

User Agent (Browser)
   ↓
1. ユーザーがSPのログインページにアクセス
   ↓
2. SPがAuthnRequestを生成、ブラウザを経由してIdPへ送信
   ↓
3. ユーザーがIdPで認証(パスワード、MFA等)
   ↓
4. IdPがSAML ResponseをACSにPOST
   ↓
5. ブラウザがFormをAutoSubmit
   ↓
6. SPがResponseを検証、セッション発行
   ↓
7. ユーザーが保護されたリソースにアクセス可能

Enhanced Client or Proxy Profile

OutlookなどのリッチクライアントでのSSO実装

メタデータ交換

IdPメタデータ

IdPが公開する、SPが信頼するための情報源

<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
  entityID="https://idp.example.com">

  <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

    <KeyDescriptor use="signing">
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data>
          <X509Certificate>
            MIIDXTCCAkWgAwIBAgIJAKHHCgVDRV2dMA0GCSqGSIb3...
          </X509Certificate>
        </X509Data>
      </KeyInfo>
    </KeyDescriptor>

    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
      Location="https://idp.example.com/sso"/>

    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      Location="https://idp.example.com/sso"/>

    <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>

  </IDPSSODescriptor>
</EntityDescriptor>

SPメタデータ

SPが公開する、IdPが信頼するための情報源

<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
  entityID="https://sp.example.com">

  <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

    <KeyDescriptor use="encryption">
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data>
          <X509Certificate>
            MIIDXTCCAkWgAwIBAgIJAKHHCgVDRV2dMA0GCSqGSIb3...
          </X509Certificate>
        </X509Data>
      </KeyInfo>
    </KeyDescriptor>

    <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      Location="https://sp.example.com/acs" isDefault="true" index="0"/>

    <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
      Location="https://sp.example.com/acs-redirect" index="1"/>

  </SPSSODescriptor>
</EntityDescriptor>

LOCKED MSO でのSAML設定項目

LOCKED MSO はSAML認証に対応しており、SAMLに対応したクラウドサービスとSSOで連携できます。設定時に決めることになる項目と、実務でよく採る値は次のとおりです。

【認証方式】
- プロトコル: SAML 2.0
- NameID Format: emailAddress(SaaS連携で一般的)
- Binding: HTTP-POST
- 署名アルゴリズム: SHA-256
- Assertionの暗号化: AES-256

【属性マッピング】
IdPが送る属性 → サービス側の項目
- mail → メールアドレス
- givenName → 名
- sn → 姓
- department → 部門

【有効期間】
- Assertionの有効期限: 5分程度
- セッションの有効期限: 業務時間に合わせる

実装上の注意点

証明書の更新管理

SAML署名用証明書は1〜3年程度の有効期限で作られることが多く、期限切れに気づかないまま当日を迎えると、SSO経由のログインが一斉に止まります。期限は監視の対象として持ちます。切り替え期間中は、新旧どちらの証明書でも署名検証が通るようにしておくと安全です。メタデータをURLで公開しておくと差し替えを伝えやすくなりますが、自動で反映されるかはSP側の実装次第です。SPが定期的にメタデータを再取得する機能を持ち、その設定が有効になっていなければ、初回にインポートした内容のまま固定され、古い証明書を使い続けることになります。切り替えの前に、そこを確認します。

時刻同期(ClockSkew)

Assertionの有効性は、IssueInstant と NotBefore / NotOnOrAfter の時刻で判定します。IdPとSPのサーバー時刻がずれていると、正しく発行されたAssertionでも期限切れや発行前と見なされて認証が失敗します。双方でNTPによる時刻同期を前提にしたうえで、許容するズレを数十秒の幅で設定しておきます。

まとめ

SAML 2.0は要素の数が多く複雑に見えますが、Assertionの中身、それを運ぶBinding、成否を伝えるStatusCodeの3つに分けて見れば、設定のどこでつまずいているかは切り分けられます。連携作業で実際に詰まるのはNameID Formatの不一致と時刻ズレ、それに証明書の期限切れで、いずれも事前に確認できる項目です。LOCKED MSO は、この複雑さを管理画面の設定項目に落とし込んだ形でSAML SSOを提供しています。


参考資料・外部リンク

関連記事

LOCKEDの詳細を見る

シングルサインオン・認証管理でお悩みなら、LOCKEDの無料デモをお試しください。

資料請求・デモ依頼はこちら →

商標について:本記事に記載されているOkta、OneLogin、Azure AD等の製品名・サービス名は、各社の商標または登録商標です。

免責事項:本記事の情報は執筆時点のものであり、各製品の最新の機能・料金・仕様については、各社の公式サイトをご確認ください。本記事の内容に基づく判断・行動について、当社は一切の責任を負いかねます。

LOCKED MSO

この課題、LOCKEDで解決できます

「IDaaS導入RFPテンプレート」など、検討に役立つ資料を無料でご用意しています

LOCKEDシリーズの詳細資料を無料でダウンロード

導入事例、機能詳細、他社比較など、検討に必要な情報をまとめた資料をご用意しています

まずは資料で詳細を確認

製品資料で機能・料金・導入事例をまとめてご確認いただけます

資料をダウンロード