Keycloakで外部IDPを使用したSAML認証


#OpenAM設定(IDP登録)

####1. OpenAM Dockerイメージ起動
OpenAMの公式Dockerイメージから起動。Keycloakのメタデータを設定する際に、OpenAMからKeycloakへの通信が必要なため、/etc/hostsにkeycloakの宛先を設定。

```
docker run -h idp-openam.app.com --add-host=keycloak-broker.com:192.168.65.2  -p 80890:8080 --name idp-opemam.app.com openidentityplatform/openam
```

####2. IDP登録
Configure SAMLLv2 Provider > Created Hosted identity Provider
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398780/6abbc5c3-cd1e-7c00-8caa-fa57f56e0631.png)

####3. NameID属性マッピング
Applications > SAML 2.0 > エンティティプロバイダから作成したプロバイダを選択。
`urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified=uid`を「追加」
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398780/ba1f0829-8083-a457-06dc-bc7af2249deb.png)

#Keycloak設定

####1. レルム作成
「Add Realm」→ 「Name」に任意のレルム名(sample-realm)を入力
####2. 認証ユーザー作成
a. Data Stores > 対象 > 新規から認証ユーザーを作成
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398780/62ac604d-5f02-2f57-504d-d7bfab1bca4b.png)
####3. Keycloak初回ログイン時認証方式を作成
a.「Authentication」→ 「New」をクリック
b.  任意のAlias(SAML_First_broker)を入力
c. 「Add Execution」→「Flows」→「Provider」で以下2つを選択
　- Create User If Unique
　- Automatically Set Existing User
d. ALTERNATIVEを選択
####4. Identity Provider登録
Identity Peoviders > Add Provider > SAML v2.0を選択

Import from URLにOpenAMのIDPメタデータ取得用URLを入力し「Import」

`http://idp-openam.app.com:8090/openam/saml2/jsp/exportmetadata.jsp`
設定内容が以下の通りになっていることを確認。

- HTTP Post Binding
- SAMLアサーション署名検証
- SAML認証要求
- NameID形式(unspecified)

```
・Alias
　- saml-sample-provider
・Enabled
　- ON
・First Login Flow
　- SAML_First_broker
・NameID Policy Format
　- Unspecified
・Principal Type
　- Subject NameID
・HTTP-POST Binding Response
　- ON
・HTTP-POST Binding Logout
　- ON
・Want AuthnRequests Signed
　- ON
・Want Assertion Signed
　- ON
・Want Assertion Encrypt
　- ON
・Validate Signature
　- ON
```

####5. ロールの作成
a. Role > Realm Roles > Add Roleをクリック
b. Role Nameに「user」を入力

####6. ユーザー作成
a. Users > Add Userを選択し、Username(testuser)を入力
b. Role Mappings > Available Rolesの「user」ロールをAssigned Rolesに追加

####7. SAMLクライアント作成

a. Clients > Create > Client Protocolで「saml」選択し「Save」

- クライアントIDはIssuerの値を入力
- アサーション署名検証
- HTTP POST Binding
- Master SAML Processing URLがアサーションコンシューマーURLとなる

```
・Client ID
　- http://sp-app.com:8085/app-profile-saml/
・Enabled
　- ON
・Sign Assertion
　- ON
・Encrypt Assertion
　- ON
・Force POST Binding
　- ON
・Force Name ID Format
　- ON
・Name ID Format
　- username
・Valid Redirect URIs
　- http://sp-app.com:8085/app-profile-saml/*
・Base URL
　- http://sp-app.com:8085/app-profile-saml/
・Master SAML Processing URL
　- http://sp-app.com:8085/app-profile-saml/saml
・IDP Initiated SSO URL Name
　- sso
　- Target IDP initiated SSO URL: http://keycloak-broker.com:8080/auth/realms/example-realm/protocol/saml/clients/sso
・IDP Initiated SSO Relay State
　- http://sp-app.com:8085/app-profile-saml/
```

b. Mappers > Add Buildtinを選択
　- X500 email,role list,X500 givenName,X500 surnameがリストに表示されるのですべてAddのチェックを付けて「Add selected」をクリック

c. クライアントアダプター定義ファイルをダウンロード
　- Clients > Installation > Downloadをクリック
　- Format Option : Keycloak SAML Adapter keycloak-saml.xmlを選択し「Download」をクリック

d. keycloak-saml.xmlに秘密鍵/証明書を追記

- logoutPageにログアウトURIを追記
- Key signing="true"
- PrivateKeyPemに秘密鍵
- CertificatePemに証明書

```keycloak-saml.xml
<keycloak-saml-adapter>
    <SP entityID="http://sp-app.com:8085/app-profile-saml/"
      sslPolicy="EXTERNAL"
      logoutPage="/Logout.jsp">
        <Keys>
            <Key signing="true">
      <PrivateKeyPem>
         MIIEpAIBAAKCAQEAn+VeV9b2lNyCrKlGIhcpzWki38V04fASKHMIIzqKODz+3BRPUVXHKWgq8b6YyQit+qHL1G79yhkEMNEMXO53nNZyt9bCxrnCy//4rUnDWmFACHlelaWAmmZrCiO+0drwA9aQsc0r+xKrSvDhYsCn・・・
      </PrivateKeyPem>
      <CertificatePem>
         MIIC5TCCAc0CBgF6xGEu3zANBgkqhkiG9w0BAQsFADA2MTQwMgYDVQQDDCtodHRwOi8vc3AtYXBwLmNvbS0wMTo4MDg2L2FwcC1wcm9maWxlLXNhbWwvMB4XDTIxMDcyMDE0NDQwMVoXDTMxMDcyMD・・・
      </CertificatePem>
            </Key>
        </Keys>
        <IDP entityID="idp">
            <SingleSignOnService signRequest="false"
                                 validateResponseSignature="false"
                                 validateAssertionSignature="false"
                                 requestBinding="POST"
                                 bindingUrl="http://keycloak-broker.com:8080/auth/realms/example-realm/protocol/saml"/>
            <SingleLogoutService signRequest="false"
                                 signResponse="false"
                                 validateRequestSignature="false"
                                 validateResponseSignature="false"
                                 requestBinding="POST"
                                 responseBinding="POST"
                                 postBindingUrl="http://keycloak-broker.com:8080/auth/realms/example-realm/protocol/saml"
                                 redirectBindingUrl="http://keycloak-broker.com:8080/auth/realms/example-realm/protocol/saml"/>
        </IDP>
    </SP>
</keycloak-saml-adapter>
```

#OpenAM設定(Keycloak Broker設定)
####1. Service Provider(Keycloak Broker)登録
a. Configure SAMLLv2 Provider > Configure Remote Service Providerを選択。
「メタデータが配置されているURL」にKeycloakのメタデータ取得用URLを入力。※ トラストサークルは既存のトラストサークル(openam-01)に追加。
`http://keycloak-broker.com:8080/auth/realms/sample-realm/broker/saml-sample-provider/endpoint/descriptor`

#WildFly(Service Provider)設定
####1. クライアントアダプターインストール
今回は、サービスプロバイダーをWildFly上で動かすため、WildFly用のSAMLクライアントアダプターをインストール
※クライアントアダプターインストール (実行前にアプリサーバーが起動していることを確認)

```
wget https://downloads.jboss.org/keycloak/8.0.1/adapters/saml/keycloak-saml-wildfly-adapter-dist-8.0.1.zip 
cp keycloak-saml-wildfly-adapter-dist-8.0.1.zip ./opt/wildfly-16.0.0.Final
cd /opt/wildfly-16.0.0.Final
unzip keycloak-saml-wildfly-adapter-dist-8.0.1.zip
./bin/jboss-cli.sh -c --file=bin/adapter-elytron-install-saml.cli 
```

successと表示されることを確認。

```
{"outcome" => "success"}{ "outcome" => "success", "response-headers" => { "operation-requires-reload" => true, "process-state" => "reload-required" }}{ "outcome" => "success", "response-headers" => {"process-state" => "reload-required"}}{ "outcome" => "success", "response-headers" => {"process-state" => "reload-required"}}{ "outcome" => "success", "response-headers" => {"process-state" => "reload-required"}}{ "outcome" => "success", "response-headers" => {"process-state" => "reload-required"}}{ "outcome" => "success", "response-headers" => {"process-state" => "reload-required"}}{ "outcome" => "success", "response-headers" => {"process-state" => "reload-required"}}{ "outcome" => "success", "response-headers" => {"process-state" => "reload-required"}}
```

- url-patternに保護対象パス
- role-nameに許可対象ロール名

```web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   version="3.0">
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>app</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>KEYCLOAK-SAML</auth-method>
    </login-config>
    <security-role>
        <role-name>user</role-name>
    </security-role>
</web-app>
```

####2. SAML用サンプルアプリデプロイ

```
sudo wget https://github.com/keycloak/keycloak-quickstarts/archive/latest.zip 
unzip latest.zip
cd keycloak-quickstarts-latest
mkdir app-profile-saml-jee-jsp/config
#「4-3.」でダウンロードした定義ファイル(keycloak-saml.xml)をconfig直下に配置
/opt/apache-maven-3.6.3/bin/mvn clean wildfly:deploy
```

#動作検証

1. WildFly起動

```
su -s /bin/bash  - wildfly -c "/opt/wildfly/bin/standalone.sh -b=0.0.0.0 -bmanagement=0.0.0.0"
```

2. 以下URLにアクセス(IDP-Initiated)
`http://keycloak-broker.com:8080/auth/realms/example-realm/protocol/saml/clients/sso`

3. ログイン情報を入力
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398780/6faca3fe-0444-34ec-6ab4-194b1087c3af.png)

4. サービスプロバイダーにリダイレクト
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398780/74ac6152-6c7e-3a69-8c7f-02b9c7e67595.png)