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>