🎨

Keycloak の SAML Artifact Binding について試してみた

2021/05/22に公開

SAML Artifact Binding について

Keycloak 13.0 がリリースされ、SAMLのArtifact Bindingが新たにサポートされるようになりました。

https://github.com/keycloak/keycloak/pull/7756

Keycloak 13.0 のIdP Metadataについても以下のようにArtifact Bindingが記載されています。
urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact
Artifact Binding のときに利用される Artifact Resolution Service URLも追加されています。

<md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml/resolve" index="0"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://keycloak.example.jp/auth/realms/master/protocol/saml"/>

SP-Initiated SSO Artifact Bindingのフロー図はOASISのドキュメントに記載されています。
HTTP Redirect Binding や HTTP POST Bindingと異なるのは

  • SAML Assertionをリダイレクトを使って、ブラウザ経由でやりとりしないこと
  • Service Provider-Identity Provider間で直接通信が行われること

です。SAMLartというパラメータをリダイレクトでブラウザを経由し、Identity ProviderからService Providerに渡します。
Service Providerは受け取ったSAMLartを使い、Identity Providerの Artifact Resolution Service というエンドポイントにリクエストを行い、SAML Assertionを取得します。
SAML Tracerなどの拡張機能でSAML Assertionを確認することができますが、Artifact Bindingのときはブラウザを経由しないためSAML Assertionについては確認することができません。
今回動かしてみたときのフローはこのようになりました。
Service Providerにはmod_auth_mellonを利用しています。

SAML Artifact Binding Flow

一般的?なHTTP Redirect BindingやHTTP POST Bindingを使ったフローはこのような感じで、Service Provider-Identity Provider間の直接の通信がありません。

SAML Regular Flow

SAMLart と Artifact Resolver Request

図の⑤〜⑥のリクエストがどのようになっているかを確認していきます。

⑤ SAMLart Request

GET
http://mellon.example.com/mellon/artifactResponse?SAMLart=AAQAACRJzLlvUqFqQAWDmZs9vcH03UM5c7mj8dNwokD5HYob%2BGH%2BV8JeB8c%3D&
RelayState=http%3A%2F%2Fmellon.example.com%2Fcgi-bin%2Fphpinfo.php HTTP/1.1
Cookie: mellon-cookie=cookietest

HTTP/1.1 303 See Other
Date: Sat, 22 May 2021 01:46:45 GMT
Server: Apache/2.4.37 (centos) OpenSSL/1.1.1g
Set-Cookie: mellon-cookie=68ab0670328137d03d20bd0c93bfbba1; Version=1; Path=/; Domain=centos8.auth.local;
Location: http://mellon.example.com/cgi-bin/phpinfo.php

⑥ Artifact Resolver Request

POST
http://keycloak.example.jp/auth/realms/master/protocol/saml/resolve

bodyが以下です。samlp:ArtifactにSAMLartとして渡されたパラメータ値が含まれています。

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
   <s:Body>
      <samlp:ArtifactResolve ID="_622B192A65497392F298A46136D87CB1" Version="2.0" IssueInstant="2021-05-21T15:03:28Z" Destination="http:/keycloak.example.com/auth/realms/master/protocol/saml/resolve">
         <saml:Issuer>http://mellon.example.com/sp</saml:Issuer>
         <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
               <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
               <SignatureMethod Algorithm="http://www.w3.org 2001/04/xmldsig-more#rsa-sha256" />
               <Reference URI="#_622B192A65497392F298A46136D87CB1">
                  <Transforms>
                     <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                     <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </Transforms>
                  <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                  <DigestValue>xgpY9Zo9VxYhy8lLRhkjjwViXf4+FBfdEtrUuayHehU=</DigestValue>
               </Reference>
            </SignedInfo>
            <SignatureValue>KfM6gwI...VukSfxinkGDNXfC9pkRs9cSJHzOg==</SignatureValue>
            <KeyInfo>
               <X509Data>
                  <X509Certificate>MIICwTCCAakCFAN/5CZYwhcH8xbBcgA...D2cwaBDv4hdVPVZuoIvFXH4QaPi9g==</X509Certificate>
               </X509Data>
            </KeyInfo>
         </Signature>
         <samlp:Artifact>AAQAACRJzLlvUqFqQAWDmZs9vcH03UM5i5S3Wq+mAOqcNz6+DRobi/xoieA=</samlp:Artifact>
      </samlp:ArtifactResolve>
   </s:Body>
</s:Envelope>

実施環境について

Service Provider の準備(Apache Httpd/mod_auth_mellon)

Artifact Bindingに対応したService Providerの準備をします。
今回はmod_auth_mellonを利用しました。
Artifact Bindingに対応したService Providerは思っていたよりも少ないみたいです。
あとはArtifact Bindingに対応しているOSSはSimpleSAMLphpくらいでしょうか。

セットアップ

httpd と mod_auth_mellon をインストールします。

dnf install -y httpd mod_auth_mellon

Service Providerとして稼働させるため、以下のシェル実行します。第一引数がエンティティID、第二引数がmod_auth_mellonのベースURLになります。

cd /etc/httpd/saml2

/usr/libexec/mod_auth_mellon/mellon_create_metadata.sh http://mellon.example.com/sp http://mellon.example.com/mellon

Output files:
Private key:                              http_mellon.example.com_sp.key
Certificate:                              http_mellon.example.com_sp.cert
Metadata:                                 http_mellon.example.com_sp.xml
Host:                                     mellon.example.com

Endpoints:
SingleLogoutService (SOAP):               http://mellon.example.com/mellon/logout
SingleLogoutService (HTTP-Redirect):      http://mellon.example.com/mellon/logout
AssertionConsumerService (HTTP-POST):     http://mellon.example.com/mellon/postResponse
AssertionConsumerService (HTTP-Artifact): http://mellon.example.com/mellon/artifactResponse
AssertionConsumerService (PAOS):          http://mellon.example.com/mellon/paosResponse

KeyclokaのSAML Idp Metadataをダウンロードして、/etc/httpd/saml2/keycloak-idp-metadata.xmlとして、mellon_create_metadata.shで作成した鍵やメタデータと同じディレクトリに置きます。

Artifact Bindingが使われるようにするために、mellon_create_metadata.shで作成されたhttp_mellon.example.com_sp.xmlを修正します。
こちらに記載されているように Artifact Binding がデフォルトとなるようにします。

    <AssertionConsumerService
        index="0"  ⭐︎追記する
        isDefault="true" ⭐︎追記する
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
        Location="https://example.com/secret/endpoint/artifactResponse" />

そして、/etc/httpd/conf.d/auth_mellon.conf に以下の設定をし、httpdを再起動します。

MellonIdPMetadataFile /etc/httpd/saml2/keycloak-idp-metadata.xml
MellonSPPrivateKeyFile /etc/httpd/saml2/http_mellon.example.com_sp.key
MellonSPCertFile /etc/httpd/saml2/http_mellon.example.com_sp.cert
MellonSPMetadataFile /etc/httpd/saml2/http_mellon.example.com_sp.xml

Identity Providerの準備(Keycloak)

SAML クライアントの作成をします。
mellon_create_metadata.sh で作成された http_mellon.example.com_sp.xml をインポートします。

メタデータインポート

Artifact Bindingが強制されるように以下の赤枠の設定のON/OFFを実施します。

  • Force Artifact Binding:ON
  • クライアント署名が必須:OFF
  • POSTバインディングを強制:OFF

設定変更

Artifact Binding を試す

http://mellon.example.com/cgi-bin/phpinfo.php にアクセスするとSAMLのフローが開始され、先ほど記載したフロー図のように処理が行われます。

mod_auth_mellonはSAML AssertionのNameIDやAttributeを MELLON_ を頭に付けた環境変数に設定しますので、以下のように http://mellon.example.com/cgi-bin/phpinfo.php から確認することができます。

環境変数

感想

これまで、SAML Artifact Binding はフロー図をさらっと見た程度で実際に試したことがありませんでした。Artifact Bindingに興味持つ人はもうあまりいないのかもしれませんが、SAMLartやArtifact Resolver RequestはArtifact Bindingでしか利用されない部分を確認することができてよかったかなと思ってます。

Discussion