えいたろブログ

ソフトウェアエンジニアの日常学習ブログです

SAMLとは

SAMLとは

ユーザー

利用者のこと

IdP(Identity Provider)

ユーザーの認証情報を保存・管理するサービスのこと。 シングルサインオン(SSO)をする場合、ユーザーはIdPへログイン認証を行う必要がある。

SP(Service Provider)

ログイン先のサービスのこと。 SPはIdPとユーザーの認証情報をやり取りし、認証処理をする。

SAML認証の種類

SP Initiated(SP起点)とIdP Initiated(IdP起点)の2つがある。

SP Initiated(SP起点)

SP起点とは、最初にユーザーがSPにアクセスを行うパターン。 ユーザーがSPにアクセスすると、SPからIdPへリダイレクトが行われてIdP側で認証が行われる。 IdP側で未ログイン状態であった場合は、IdP側のログイン画面が表示されIdPへのログインを行う。 ログインが成功すると、今度はIdPからSPへリダイレクトが行われて、IdPから受け取った認証情報を元にSP側で認証を行い、認証に成功するとユーザーはSPへログイン成功となる。

IdP Initiated(IdP起点)

IdP起点とは、最初にユーザーがIdPの画面から利用したいSPを選択して利用するパターンになる。 ユーザーがIdPへログインを行い、IdPのSP一覧画面から利用したいSPを選択すると、対象のSPに認証情報が送信されてログイン認証が行われる。

事前に設定が必要な情報

SP側

  • ログインURL →SPからIdPへリダイレクトを行う際のリダイレクト先URL
  • ログアウトURL →SPからログアウトした後のリダイレクト先URL。
  • エンティティID →IdPをグローバルに一意に認識するためのID。(IdPから取得)
  • IdPの証明書 →IdPが認証応答の署名に用いる秘密鍵に対応する公開鍵。(IdPから取得)

IdP側

  • Assertion Consumer Service URL →IdPからSPへリダイレクトを行う際のリダイレクト先URL。
  • エンティティID →SPをグローバルに一意に認識するためのID。(IdPから取得)

SP Initiated 初回認証フロー

IdP側にセッションがない場合

sequenceDiagram
    participant user as ユーザー
    participant sp as SP
    participant idp as IdP
    Note over sp,idp: 事前に必要な情報を設定<br>(信頼関係構築)
    user->>sp: SPへアクセス GET
    sp->>user: SAML認証要求を発行(IdPに問い合わせ要求) 302リダイレクト
    Note left of sp: AuthnRequest
    user->>idp: SAML認証要求を送信(ログイン認証要求) GET
    Note right of user: AuthnRequest
    idp->>user: 認証画面を表示(ログイン画面などを表示) 200OK
    user->>idp: 認証情報を送信 POST
    idp->>idp: 認証処理
    idp->>user: SAML認証応答を発行(IdPの秘密鍵で署名) 303リダイレクト
    Note left of idp: Response
    user->>sp: SAML認証応答を送信 POST
    Note right of user: Response
    sp->>sp: SAML認証応答をIdPの公開鍵で検証
    sp->>user: SPにログイン成功(SP側に紐づくアカウント) 200OK

SP Initiated 2回目認証フロー

IdP側にセッションがある場合

sequenceDiagram
    participant user as ユーザー
    participant sp as SP
    participant idp as IdP
    Note over sp,idp: 事前に必要な情報を設定<br>(信頼関係構築)
    user->>sp: SPへアクセス GET
    sp->>user: SAML認証要求を発行(IdPに問い合わせ要求) 302リダイレクト
    Note left of sp: AuthnRequest
    user->>idp: SAML認証要求を送信(ログイン認証要求) GET
    Note right of user: AuthnRequest
    idp->>user: SAML認証応答を発行(IdPの秘密鍵で署名) 303リダイレクト
    Note left of idp: Response
    user->>sp: SAML認証応答を送信 POST
    Note right of user: Response
    sp->>sp: SAML認証応答をIdPの公開鍵で検証
    sp->>user: SPにログイン成功(SP側に紐づくアカウント) 200OK

AuthnRequestの中身

<?xml version="1.0"?>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                    ID="identifier_1"
                    Version="2.0"
                    IssueInstant="2023-10-25T07:39:28.807Z"
                    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                    Destination="https://idp.example.com/"
                    AssertionConsumerServiceURL="https://sp.example.com/">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://sp.example.com/</saml:Issuer>
  <samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                      Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
                      AllowCreate="true" />
</samlp:AuthnRequest>

Responseの中身

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<samlp:Response xmlns="urn:oasis:names:tc:SAML:2.0:assertion"
                xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
                Destination="https://sp.example.com/"
                ID="identifier_2"
                InResponseTo="identifier_1"
                IssueInstant="2023-10-25T07:39:28Z"
                Version="2.0">
  <Issuer>https://idp.example.com/</Issuer>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
  </samlp:Status>
  <Assertion ID="identifier_3"
             IssueInstant="2023-10-25T07:39:28Z"
             Version="2.0">
    <Issuer>https://idp.example.com/</Issuer>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
      ...
    </Signature>
    <Subject>
      <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
              SPNameQualifer="https://sp.example.com/">UIDxxxxxxxxx</NameID>
      <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <SubjectConfirmationData InResponseTo="identifier_1"
                                 NotOnOrAfter="2023-10-25T07:49:28Z"
                                 Recipient="https://sp.example.com/" />
      </SubjectConfirmation>
    </Subject>
    <Conditions NotBefore="2023-10-25T07:34:28Z"
                NotOnOrAfter="2023-10-25T07:49:28Z">
      <AudienceRestriction>
        <Audience>https://sp.example.com/</Audience>
      </AudienceRestriction>
    </Conditions>
    <AttributeStatement>
      <Attribute Name="UID">
        <AttributeValue>UIDxxxxxxxxx</AttributeValue>
      </Attribute>
    </AttributeStatement>
    <AuthnStatement AuthnInstant="2023-10-25T07:39:28Z"
                    SessionIndex="identifier_3">
      <AuthnContext>
        <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
      </AuthnContext>
    </AuthnStatement>
  </Assertion>
</samlp:Response>

参考