Keycloak の SAML Artifact Binding について試してみた
SAML Artifact Binding について
Keycloak 13.0 がリリースされ、SAMLのArtifact Bindingが新たにサポートされるようになりました。
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を利用しています。
一般的?なHTTP Redirect BindingやHTTP POST Bindingを使ったフローはこのような感じで、Service Provider-Identity Provider間の直接の通信がありません。
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