Keycloakを使ってSAMLを理解する#2

Azure上のCentOSに、Keycloakとサンプルアプリを入れて、SAMLを使ったログインの動作検証を行ったメモです。

- [Keycloakを使ってSAMLを理解する#1](https://qiita.com/gebo/items/766855b346324c8d61df)
- **Keycloakを使ってSAMLを理解する#2**

前回はAzure上のCentOSに、Keycloak（IdP)とサンプルアプリ(SP)を入れて起動させるところまでやりました。
今回はKeycloak（IdP)とサンプルアプリ(SP)の連携フローを見ていきます。


#フロー図
`wireshark`でHTTPをキャプチャして連携を調査しました。

- User観点ではLOGINボタンをクリックして表示される認証画面からIDとパスワードを入力する一般的なログイン操作。
- 操作の入り口はSPだけど、認証画面はIdPが出して、認証後はまたSPに戻っている。ユーザー観点は一般的なログインだが、SPとIdPが別というところがポイント。
- 裏ではかなりあっちこっちやっている。

![Flow_SAML.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/602053ad-4d85-f028-ef50-b884ddb7e33c.png)


**Please Login画面**
<img width="300" alt="Keycloak_Example_App.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/0fb0f448-c452-8a4d-d62a-c14fc2246eab.png">

**認証画面**
<img width="300" alt="Log_in_to_Keycloak-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/e141c151-876b-7d18-3029-eab6e3bd9fb0.png">

**ユーザープロファイル画面**
<img width="300" alt="Keycloak_SAML_Example_App.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/92819dfa-5315-8c36-1951-e8d9e191418a.png">


#1 Start SP

##Request
まずはブラウザからサンプルSP(app-profile-saml)にアクセスします。

```HTTP:app-profile-samlへのアクセス
GET http://x.x.x.x:8080/app-profile-saml/ HTTP/1.1
```

##Response
レスポンスでPlease Login画面が返ってきます。

```HTTP:app-profile-samlからのレスポンス
HTTP/1.1 200 OK
Content-Type:text/html
```

<img width="300" alt="Keycloak_Example_App.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/0fb0f448-c452-8a4d-d62a-c14fc2246eab.png">


```html:Please_Login_画面

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
        <title>Keycloak Example App</title>
        <link rel="stylesheet" type="text/css" href="styles.css"/>
    </head>
    
    <body>
        <div class="wrapper" id="welcome">
            <div class="menu">
                <button name="loginBtn" onclick="location.href = 'profile.jsp'" type="button">Login</button>
            </div>

            <div class="content">
                <div class="message">Please login</div>
            </div>
        </div>
    </body>
</html>
```


#2 Start Login

##Request
LOGINボタンをクリックしてログインを開始します。

<img width="300" alt="Keycloak_Example_App-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/f52bdd13-71f3-0036-b364-0f8c12d5924d.png">


```HTTP:LOGINボタンクリック時のアクション
GET http://x.x.x.x:8080/app-profile-saml/profile.jsp HTTP/1.1
```

##Response
このレスポンスにSAMLコマンドが詰まっています。

```HTTP:LOGINボタンクリックのレスポンス
HTTP/1.1 200 OK
Content-Type:text/html
```

```html:Authentication_Redirect画面(リダイレクト)
<HTML>
    <HEAD>
        <TITLE>Authentication Redirect</TITLE>
    </HEAD>
    <BODY Onload="document.forms[0].submit()">
        <FORM METHOD="POST" ACTION="http://x.x.x.x:8080/auth/realms/master/protocol/saml">
            <INPUT TYPE="HIDDEN" NAME="SAMLRequest" VALUE="PHNhbWxwOkF1...中略...cXVlc3Q+"/>
            <p>Redirecting, please wait.</p>
            <NOSCRIPT>
                <P>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.</P>
                <INPUT TYPE="SUBMIT" VALUE="CONTINUE" />
            </NOSCRIPT>
        </FORM>
    </BODY>
</HTML>
```

Onloadでsubumit()しているので、そのままリダイレクトすることになります。
リダイレクト先は
`http://x.x.x.x:8080/auth/realms/master/protocol/saml`
`POST`で`SAMLRequest`をするようです。


#3 SAML AuthnRequest

##Request
先ほどのリダイレクトの流れから、そのままPOSTになります。
POST先が**IdP(Keycloak)**なのがポイントです。

```HTTP:Keycloak_IdP-EndPointへのPOST
POST http://x.x.x.x:8080/auth/realms/master/protocol/saml HTTP/1.1
Content-Type: application/x-www-form-urlencoded
SAMLRequest=PHNhbWxwOkF1...中略...cXVlc3Q+
```

この`SAML Request`はエンコードされているのでデコードしてみましょう。
SAMLのコマンドは以下のサイトでデコードすることができます。
- [Base64 Decode + Inflate](https://www.samltool.com/decode.php)

##SAML AuthnRequest解説
`SAML Request`をデコードするとこんなXMLが出てきます。
SAMLの**AuthnRequest**というコマンドで、IdPに認証情報を要求するコマンドです。

```XML:SAML_AuthnRequest
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
                    xmlns="urn:oasis:names:tc:SAML:2.0:assertion" 
                    Destination="http://x.x.x.x:8080/auth/realms/master/protocol/saml" 
                    ForceAuthn="false" 
                    ID="ID_2c456903-1b09-41be-aa60-3d4372c75c65" 
                    IsPassive="false" 
                    IssueInstant="2020-01-19T02:51:45.961Z" 
                    Version="2.0"
                    >
                    
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">app-profile-saml</saml:Issuer>

  <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
    <dsig:SignedInfo>
      <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <dsig:Reference URI="#ID_2c456903-1b09-41be-aa60-3d4372c75c65">
        <dsig:Transforms>
          <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <dsig:DigestValue>UplUbEGua/Ctgk3OItxsePMwLptdMIOXGaLuOvzNQSI=</dsig:DigestValue>
      </dsig:Reference>
    </dsig:SignedInfo>
    <dsig:SignatureValue>KmPeo9/kJSds...中略...Jbja4W9sqESWOOsg==</dsig:SignatureValue>
    <dsig:KeyInfo>
      <dsig:KeyValue>
        <dsig:RSAKeyValue>
          <dsig:Modulus>q4FMfjqo...中略...0bbIDp32+bn0dpMmcMcUQ==</dsig:Modulus>
          <dsig:Exponent>AQAB</dsig:Exponent>
        </dsig:RSAKeyValue>
      </dsig:KeyValue>
    </dsig:KeyInfo>
  </dsig:Signature>

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

|要素|属性|説明|
|:-:|:-:|:--|
|samlp:AuthnRequest||IdPに認証情報を要求する|
||Destination|宛先|
|   |ForceAuthn|trueの場合、認証を強制される|
|   |ID|発行元が生成したID|
|   |IsPassive|trueの場合、IdPにログインしていなくても、ユーザーに認証を要求しないようにする|
|   |IssueInstant|生成日時|
|- saml:Issuer|   |発行元|
|- dsig:Signature|   |XML署名|
|- samlp:NameIDPolicy|   |IdPがレスポンスする際の形式を指定する|
|   |AllowCreate|？|
|   |Format|レスポンス形式|

**わかったこと**
- **SPはIdPに認証情報をくれとリクエストしている(AuthnRequest)。**
- **AuthnRequestには電子署名がついている。**
- **受け取るほう(IdP)は電子署名を検証してリクエストがちゃんとしているものだと確認するのだろう。**
- **この電子署名がSAMLのキモなんだろう。しかし真剣に掘っていくと沼にハマるのでこの辺でやめておこう。**
- **IdP側はAuthnRequestを受けて、認証情報がない(まだログインしていない)からこの後ログイン画面にリダイレクトさせるのだろう。**

##Response
レスポンスはURLリダイレクトステータスです。
先ほどの説明の通り、
**SPは認証情報を要求した(AuthnRequest)が、IdP(Keycloak)側に認証情報がない(まだログインしていない)ので、認証画面にリダイレクトされた**
ということです。

```HTTP:Keycloak_Authenticate-Endpointへのリダイレクト
HTTP/1.1 302 Found
Location:http://x.x.x.x:8080/auth/realms/master/login-actions/authenticate?client_id=app-profile-saml&tab_id=Rlo47UVsNoQ
```


#4 Authenticate

#Request
リダイレクトでKeycloakの認証エンドポイントにすっとんでいきます。
パラメータのclient_idは見ればわかるのですが、tab_idは何なのかわかりません...

```HTTP:Keycloak_Authenticate-Endpointへアクセス
GET http://x.x.x.x:8080/auth/realms/master/login-actions/authenticate
?client_id=app-profile-saml
&tab_id=Rlo47UVsNoQ HTTP/1.1
```

#Response
Keycloakが持っている標準の認証画面です。

```HTTP:
HTTP/1.1 200 OK
Content-Type:text/html
```

<img width="300" alt="Log_in_to_Keycloak-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/e141c151-876b-7d18-3029-eab6e3bd9fb0.png">

```html:認証画面
<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="robots" content="noindex, nofollow">

            <meta name="viewport" content="width=device-width,initial-scale=1"/>
    <title>Log in to Keycloak</title>
</head>

<body class="">
  <div class="login-pf-page">
    <div id="kc-header" class="login-pf-page-header">
      <div id="kc-header-wrapper" class=""><div class="kc-logo-text"><span>Keycloak</span></div></div>
    </div>
    <div class="card-pf ">
      <header class="login-pf-header">
        <h1 id="kc-page-title">Log In</h1>
      </header>
      <div id="kc-content">
        <div id="kc-content-wrapper">
          <div id="kc-form" >
            <div id="kc-form-wrapper" >
              <form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="http://x.x.x.x:8080/auth/realms/master/login-actions/authenticate?session_code=SbuptnMgKOwLkWkPwF-7WgktStwhKlG99fN-6LAV8_Q&amp;execution=c5044823-9e8d-4399-8ce8-9c3091a3c264&amp;client_id=app-profile-saml&amp;tab_id=Rlo47UVsNoQ" method="post">
                <div class="form-group">
                    <label for="username" class="control-label">Username or email</label>
                        <input tabindex="1" id="username" class="form-control" name="username" value=""  type="text" autofocus autocomplete="off" />
                </div>

                <div class="form-group">
                    <label for="password" class="control-label">Password</label>
                    <input tabindex="2" id="password" class="form-control" name="password" type="password" autocomplete="off" />
                </div>

                <div class="form-group login-pf-settings">
                    <div id="kc-form-options">
                        </div>
                        <div class=""></div>
                    </div>
                    <div id="kc-form-buttons" class="form-group">
                      <input type="hidden" id="id-hidden-input" name="credentialId" />
                      <input tabindex="4" class="btn btn-primary btn-block btn-lg" name="login" id="kc-login" type="submit" value="Log In"/>
                    </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
</html>
```


#Request
KeycloakのUser/Passwordを入力してログインします。
パラメータで`client_id`と`tab_id`はさっき使ったものをそのまま使うようですが、
`session_code`,`execution`という謎のパラメタが増えています。

```HTTP:認証のPOST
POST http://x.x.x.x:8080/auth/realms/master/login-actions/authenticate
?session_code=SbuptnMgKOwLkWkPwF-7WgktStwhKlG99fN-6LAV8_Q
&execution=c5044823-9e8d-4399-8ce8-9c3091a3c264
&client_id=app-profile-saml
&tab_id=Rlo47UVsNoQ HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=test1
password=test1
credential=""
```

~~usernameとpasswordって平文でおくっているけど、いいんか？というところはきにしない~~

#Response
このレスポンスが**SAML Response**をリダイレクトするhtmlです。

```HTTP:認証のレスポンス
HTTP/1.1 200 OK
Content-Type:text/html
```

```html:Authentication_Redirect画面(リダイレクト)
<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="robots" content="noindex, nofollow">

    <meta name="viewport" content="width=device-width,initial-scale=1"/>
    <title>Log in to Keycloak</title>
    
    <SCRIPT>
      if (typeof history.replaceState === 'function')
      {  
        history.replaceState({},
          "some title",
          "http://x.x.x.x:8080/auth/realms/master/login-actions/authenticate?client_id=app-profile-saml&tab_id=Rlo47UVsNoQ"
        );
      }
    </SCRIPT>
</head>

<body class="">
    <div class="login-pf-page">
    
      <div id="kc-header" class="login-pf-page-header">
        <div id="kc-header-wrapper" class="">
          <div class="kc-logo-text">
            <span>Keycloak</span>
          </div>
        </div>
      </div>
      
      <div class="card-pf ">

        <header class="login-pf-header">
          <h1 id="kc-page-title">Authentication Redirect</h1>
        </header>

        <div id="kc-content">
          <div id="kc-content-wrapper">
            <script>
              window.onload = function()
                {
                  document.forms[0].submit()
                };
            </script>
            <p>Redirecting, please wait.</p>
            <form name="saml-post-binding" method="post" action="http://x.x.x.x:8080/app-profile-saml/saml">
                <input type="hidden" name="SAMLResponse" value="PHNhbWxwOlJl...中略...mVzcG9uc2U+"/>
                <noscript>
                  <p>JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue. </p>
                  <input type="submit" value="Continue"/>
                </noscript>
            </form>
          </div>
          
        </div>
      </div>
      
    </div>
  </body>
</html>
```

↑のHTMLはちょっと長いのですが、結局`Onload`で`subumit()`しているので、表示したらすぐそのままリダイレクトすることになります。


#5 SAML Response

##Request
リダイレクト先は
`http://x.x.x.x:8080/app-profile-saml/saml`
`POST`で`SAMLResponse`をするようです。

```HTTP:Keycloak_IdP-EndpointへのPOST
POST http://x.x.x.x:8080/app-profile-saml/saml HTTP/1.1
Content-Type: application/x-www-form-urlencoded
SAMLResponse=PHNhbWxwOlJl...中略...mVzcG9uc2U+
```

`SAMLResponse`を[Base64 Decode + Inflate](https://www.samltool.com/decode.php)でデコードしてみます。

###SAML Response解説
デコードした`SAML Response`です。やたら長いです。

```XML:SAML_Response
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
                xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
                Destination="http://x.x.x.x:8080/app-profile-saml/saml" 
                ID="ID_a691f142-51a6-433b-a456-db89291aab67" 
                InResponseTo="ID_2c456903-1b09-41be-aa60-3d4372c75c65" 
                IssueInstant="2020-01-19T02:51:53.685Z" 
                Version="2.0"
                >
  <saml:Issuer>http://x.x.x.x:8080/auth/realms/master</saml:Issuer>
 
  <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
    <dsig:SignedInfo>
      <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <dsig:Reference URI="#ID_a691f142-51a6-433b-a456-db89291aab67">
        <dsig:Transforms>
          <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <dsig:DigestValue>uFCjz6gyMq0Nulz5c5X7OMaBAN9jQAN51s64I6viLJ0=</dsig:DigestValue>
      </dsig:Reference>
    </dsig:SignedInfo>
    <dsig:SignatureValue>hmFB31+6B...中略...Ykhoa/A==</dsig:SignatureValue>
    <dsig:KeyInfo>
      <dsig:KeyName>3tndQNc2V6QidH4jGbkZwsjloMRqUfSMLzpPX4z9DbY</dsig:KeyName>
      <dsig:X509Data>
        <dsig:X509Certificate>MIICmzC...中略...U35PpFsrrc=</dsig:X509Certificate>
      </dsig:X509Data>
      <dsig:KeyValue>
        <dsig:RSAKeyValue>
          <dsig:Modulus>1PlG6gya5wOrz...中略...t/Pr4fPw==</dsig:Modulus>
          <dsig:Exponent>AQAB</dsig:Exponent>
        </dsig:RSAKeyValue>
      </dsig:KeyValue>
    </dsig:KeyInfo>
  </dsig:Signature>
  
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
  </samlp:Status>
  
  <saml:Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" 
                  ID="ID_25e00b6a-b615-479e-9b64-c4fcaf0ba1a8" 
                  IssueInstant="2020-01-19T02:51:53.667Z" 
                  Version="2.0"
                  >
                  
    <saml:Issuer>http://x.x.x.x:8080/auth/realms/master</saml:Issuer>

    <saml:Subject>
      <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">test1</saml:NameID>
      <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <saml:SubjectConfirmationData InResponseTo="ID_2c456903-1b09-41be-aa60-3d4372c75c65" 
                                      NotOnOrAfter="2020-01-19T02:52:51.667Z" 
                                      Recipient="http://x.x.x.x:8080/app-profile-saml/saml"
                                      />
      </saml:SubjectConfirmation>
    </saml:Subject>
    
    <saml:Conditions NotBefore="2020-01-19T02:51:51.667Z" NotOnOrAfter="2020-01-19T02:52:51.667Z">
      <saml:AudienceRestriction>
        <saml:Audience>app-profile-saml</saml:Audience>
      </saml:AudienceRestriction>
    </saml:Conditions>
    
    <saml:AuthnStatement AuthnInstant="2020-01-19T02:51:53.686Z" 
                         SessionIndex="b439dacf-e174-4f27-8623-4509692e8453::db4ef113-c646-4fc1-a4f2-91993ceac53b" 
                         SessionNotOnOrAfter="2020-01-19T12:51:53.686Z"
                         >
      <saml:AuthnContext>
        <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
      </saml:AuthnContext>
    </saml:AuthnStatement>

    <saml:AttributeStatement>
      <saml:Attribute FriendlyName="surname" Name="urn:oid:2.5.4.4" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">bbb</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute FriendlyName="email" Name="urn:oid:1.2.840.113549.1.9.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">aaa@test.com</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute FriendlyName="givenName" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">aaa</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">manage-account</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">create-realm</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">offline_access</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">view-profile</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">user</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">manage-account-links</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">uma_authorization</saml:AttributeValue>
      </saml:Attribute>
    </saml:AttributeStatement>
  </saml:Assertion>
</samlp:Response>
```

|要素|属性|説明|
|:--|:--|:--|
|samlp:Response|||
||Destination|宛先|
||ForceAuthn|trueの場合、認証を強制される|
||ID|発行元が生成したID|
||IssueInstant|生成日時|
|- saml:Issuer|   |発行元|
|- dsig:Signature|   |XML署名|
|- samlp:Status|   |処理結果Success=成功|
|- samlp:Assertion|   |**アサーション 認証結果**|
||ID||
||IssueInstant|生成日時|
|-- saml:Issuer|   |発行元|
|-- saml:Subject|   ||
|-- saml:Conditions|   ||
|-- saml:AuthnStatement|   ||
|-- saml:AttributeStatement|   ||

**わかったこと**
- **これは、認証して、ユーザーの確認取れたよ、ということなんだろう。** 
- **Assertionが認証結果でこれで誰が認証したということを特定できるのだろう。**


##Response
レスポンスはURLリダイレクトステータスです。

```HTTP:app-profile-samlへのリダイレクト指示
HTTP/1.1 302 Found
Location:http:http://x.x.x.x:8080/app-profile-saml/profile.jsp
```

##Request
リダイレクトにより飛ばされるURLは、最初にLOGINボタンをクリックしたときのURL(profile.jsp)です。

```HTTP:app-profile-samlへのアクセス
GET http://x.x.x.x:8080/app-profile-saml/profile.jsp HTTP/1.1
```

##Response
今回は認証が済んでいるので、ユーザーのプロファイルが表示されるような画面が返ってきます。

```HTTP:app-profile-samlからのレスポンス
HTTP/1.1 200 OK
Content-Type:text/html
```

<img width="300" alt="Keycloak_SAML_Example_App.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/92819dfa-5315-8c36-1951-e8d9e191418a.png">


```html:ユーザープロファイル画面
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
    <title>Keycloak SAML Example App</title>
    <link rel="stylesheet" type="text/css" href="styles.css"/>
  </head>
  
  <body>
    <div class="wrapper" id="profile">
      <div class="menu">
          <button name="logoutBtn" onclick="location.href = '?GLO=true'" type="button">Logout</button>
          <button name="accountBtn" onclick="location.href = 'http://x.x.x.x:8080/auth/realms/master/account?referrer=app-profile-saml'" type="button">Account</button>
      </div>

      <div class="content">
        <div id="profile-content" class="message">
          <table cellpadding="0" cellspacing="0">
            <tr>
              <td class="label">First name</td>
              <td><span id="firstName">aaa</span></td>
            </tr>
            <tr class="even">
              <td class="label">Last name</td>
              <td><span id="lastName">bbb</span></td>
            </tr>
            <tr>
              <td class="label">Username</td>
              <td><span id="username">test1</span></td>
            </tr>
            <tr class="even">
              <td class="label">Email</td>
              <td><span id="email">aaa@test.com</span></td>
            </tr>
          </table>
        </div>
      </div>
    </div>
  </body>
</html>
```


#おつかれさまでした

SAMLを完全に理解した。

<img width="664" alt="ダニングクルーガ効果_-_Google_検索.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/036ff0bf-0f34-a542-d515-f770c9c526dc.png">

そしてSAMLわからん...これを実装しているIdPとかSPはすごい...