LoginSignup
21
10

More than 5 years have passed since last update.

Keycloakのクライアント・アダプターを試してみる(Tomcat編)

Last updated at Posted at 2017-12-04

今日やること

Keycloakアドベンドカレンダー5日目の今回は、Tomcat 8用のクライアント・アダプター(OpenID Connect版)を試してみます。

クライアント・アダプターとは、KeycloakとID連携(SSO)し、アプリケーション保護を容易にするためのプラットフォーム固有のライブラリ群です。基本的にはアプリケーションが導入されているミドルウェア上にクライアント・アダプターをインストール/設定した上で、ユーザー連携のため多少のコードカスタマイズを実施することになります。

現在サポートされている主なプラットフォームおよびプロトコルは以下のとおりです。

  • プラットフォーム
    • Wildfly
    • JBoss EAP
    • JBoss AS
    • JBoss Fuse
    • Jetty
    • Tomcat
    • Javascript(クライアント)
  • プロトコル
    • OpenID Connect
    • SAML 2.0

:information_source: 上記以外にも、コミュニティから提供されているクライアント・アダプターが複数あります。プラットフォームとプロトコルの組み合わせによってはサポートされていないものがあるので、詳しくは参考資料の"Supported Platforms"を参照ください。

今回はTomcat 8のサンプルアプリ(examples)に対してTomcat 8用のクライアント・アダプター(OpenID Connect版)を導入し、KeycloakとID連携を行う方法を試してみます。

動作確認用のサーバー構成

今回のお試し環境はこのような感じです。
Keycloakサーバーには、demoレルムが作成されており(3日目の記事を参照)、ログイン可能なユーザーが存在していることが前提となります。

FQDN OS JDK 構成
kc-server.example.com CentOS 7.4.1708 OpenJDK 1.8.0.151 ・Keycloakサーバー 3.3.0.CR2
kc-tomcat.example.com CentOS 7.4.1708 OpenJDK 1.8.0.151 ・Tomcat 8.5.23(examplesアプリを利用)
・Tomcat 8用クライアント・アダプター(OpenID Connect版) 3.3.0.Final
ユーザー ロール
user001 user
admin001 user,admin

Tomcatに付属するexapmlesアプリケーションでは、以下のようなアクセス制御をかけることを想定します。

tomcat_acl01.png

動作確認時の各サーバーへのアクセスポートは以下のとおりです。
tomcat_port01.png

Keycloakサーバー側の設定

クライアントの追加・設定

  1. Keycloakの管理コンソールにログインします。
  2. 左メニューバーから、demoレルムを選択します。
  3. 左メニューバーで クライアント をクリックします。クライアント一覧が表示されます。
  4. 右上の 作成 ボタンを押下します。
  5. 以下のようなクライアント設定値を入力し、保存 ボタンを押下します

  6. 引き続き kc-tomcatの設定画面が表示されるので以下のような設定を行い、保存 ボタンを押下します。

  7. インストール タブを押下します。

  8. フォーマットオプションからKeycloak OIDC JSONを選択し、ダウンロードのテキストボックスに表示されているjsonを控えます。
    tomcat03.png

クライアント・アダプター側の設定

クライアント・アダプターの設定では、WAR単位で連携設定が必要です。
Webアプリケーション単位で、以下の3つの手順を実施します。

  1. $WAR_HOME/META-INF/context.xmlの配置
  2. $WAR_HOME/WEB-INF/keycloak.jsonの配置
  3. $WAR_HOME/WEB-INF/web.xmlの編集

以下、順を追って説明します。

Tomcat 8の導入

連携確認用のサンプルアプリケーションとして、Tomcat 8を導入します。

cd  /tmp
wget http://ftp.tsukuba.wide.ad.jp/software/apache/tomcat/tomcat-8/v8.5.23/bin/apache-tomcat-8.5.23.tar.gz
tar zxvf apache-tomcat-8.5.23.tar.gz -C /usr/local

Tomcat 8用のクライアント・アダプターのダウンロードと展開

Tomcat 8用のクライアント・アダプターをダウンロードして /usr/local/apache-tomcat-8.5.23/lib/ に解凍します。

cd  /tmp
wget https://downloads.jboss.org/keycloak/3.3.0.Final/adapters/keycloak-oidc/keycloak-tomcat8-adapter-dist-3.3.0.Final.tar.gz
tar zxvf keycloak-tomcat8-adapter-dist-3.3.0.Final.tar.gz -C /usr/local/apache-tomcat-8.5.23/lib/

META-INF/context.xml の配置

今回はTomcatのexamplesのWebアプリケーションに対して保護をかけるため、
対象のWARディレクトリ配下にMETA-INF/context.xmlを作成します。

この設定ではTomcatのValveとしてKeycloakAuthenticatorValveを設定しています。Valveとは、リクエストをフックするためのTomcat独自のプラグイン機構です。KeycloakとID連携を行うためのKeycloakAuthenticatorValveを設定することにより、当該アプリケーションへのリクエストが事前にフィルタされ、KeycloakとのID連携やアプリケーション保護に必要な処理が実施されるようになります。

mkdir -p /usr/local/apache-tomcat-8.5.23/webapps/examples/META-INF/
/usr/local/apache-tomcat-8.5.23/webapps/examples/META-INF/context.xml
<Context path="/examples">
    <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
</Context>

WEB-INF/keycloak.json の配置

対象のWARディレクトリのWEB-INF以下に、クライアント・アダプターの設定用のJSONファイル(keycloak.json)を配置します。
基本的に、Keycloakの管理画面で控えたjsonをそのまま設定するだけですが、今回はssl-requirednoneに変更します。

/usr/local/apache-tomcat-8.5.23/webapps/examples/WEB-INF/keycloak.json
{
  "realm": "demo",
  "auth-server-url": "https://kc-server.example.com:8443/auth",
  "ssl-required": "none",
  "resource": "kc-tomcat",
  "credentials": {
    "secret": "{Keycloakサーバー側のシークレットの値}"
  }
}
パラメータ名 必須 説明
realm Keycloak側のレルム名を指定します。
auth-server-url Keycloak側のベースURLを指定します。1
ssl-required HTTPSでのアクセスを強制するかどうか指定します。"all", "external", "none" のいずれかを指定します。デフォルトは、"external"なので、外部からはHTTPのアクセスは許可されません。
resource Keycloak側のクライアント設定のクライアントID(client-id)を指定します。
credentials Keycloak側のアクセスタイプで"confidential"を指定した場合は必須です。

:information_source: adapter-configの設定は非常に多くあるため、動作確認に必要な最低限の項目のみ記載しています。その他のパラメータに関しては、参考資料の"Java Adapter Config"を参照ください。

:information_source: 今回は、Tomcatに8080ポートでアクセス可能にするため、ssl-requiredは、noneに変更しています。ただし、本来のOIDCではセキュリティ担保のためHTTPSの利用が前提となっています。そのため、実環境ではssl-requiredallにすべきです。

WEB-INF/web.xmlの編集

examples/WEB-INF/web.xml に元から定義されている login-config の設定があるため、こちらは一旦コメントアウトします。

/usr/local/apache-tomcat-8.5.23/webapps/examples/WEB-INF/web.xml
    ・
    ・
    <!-- Default login configuration uses form-based authentication -->
    <!-- COMMENT OUT
    <login-config>
      <auth-method>FORM</auth-method>
      <realm-name>Example Form-Based Authentication Area</realm-name>
      <form-login-config>
        <form-login-page>/jsp/security/protected/login.jsp</form-login-page>
        <form-error-page>/jsp/security/protected/error.jsp</form-error-page>
      </form-login-config>
    </login-config>
    -->
    ・
    ・

クライアント・アダプターによるID連携やアプリケーション保護はJavaEE標準のセキュリティ機能と連携するため、各アプリケーションにあわせてweb.xmlに固有の設定を行う必要があります。

今回のアクセス制御の設定例では、以下のように設定します。

  • /examples/* へのアクセスはuserロールの権限が必要
  • /examples/websocket/* へのアクセスはadminロールの権限が必要
/usr/local/apache-tomcat-8.5.23/webapps/examples/WEB-INF/web.xml
    ・
    ・
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>User Area</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Admin Area</web-resource-name>
            <url-pattern>/websocket/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>this is ignored currently</realm-name>
    </login-config>

    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>user</role-name>
    </security-role>
    ・
    ・

Tomcatの起動

クライアント・アダプターの準備が整ったので、Tomcat起動します。

cd /usr/local/apache-tomcat-8.5.23/
./bin/startup.sh

動作確認

user ロールが必要なURL

  1. userロールが必要なhttp://kc-tomcat.example.com:8080/examples/ にアクセスします。
  2. Keycloakに未ログインであるため、ログイン画面にリダイレクトが発生します。
  3. userロールを持つユーザーのID/PWでログインします。
  4. http://kc-tomcat.example.com:8080/examples/ が表示されます。
    tomcat04.png

  5. adminロールが必要な http://kc-tomcat.example.com:8080/examples/websocket/echo.xhtml にアクセスします。

  6. 403(Forbidden)となり、ページは表示されません。
    tomcat05.png

userおよびadminロールが必要なURL

  1. userおよびadminロールが必要な http://kc-tomcat.example.com:8080/examples/websocket/echo.xhtml にアクセスします。
  2. Keycloakに未ログインであるため、ログイン画面にリダイレクトが発生します。
  3. user / admin の双方のロールを持つユーザーのID/PWでログインします。
  4. http://kc-tomcat.example.com:8080/examples/websocket/echo.xhtml が表示されます。
    tomcat06.png

  5. userロールが必要なhttp://kc-tomcat.example.com:8080/examples/ にアクセスします。

  6. http://kc-tomcat.example.com:8080/examples/ が表示されます。
    tomcat07.png

ユーザー情報の取得確認

上記の確認では、アクセス制御の確認はできましたがログインしたユーザー情報をどのように取得したらよいのかよく分かりません。クライアント・アダプターを利用している場合は、KeycloakのAPIを利用することで、OIDCで連携されたIDトークンの情報を簡単に取得することができます。以下のサンプル実装では、HTTPセッションからユーザー情報を取得するJSPを新たに配置して、ログイン済みのユーザー情報が取得できるかどうか確認しています。

以下のgetUserInfo.jspをWARディレクトリ直下に配置します。

/usr/local/apache-tomcat-8.5.23/webapps/examples/getUserInfo.jsp
<%@ page import="org.keycloak.KeycloakSecurityContext" %>
<%@ page import="org.keycloak.representations.IDToken" %>

<%
    // HTTPセッションからKeycloakSecurityContextを取得
    KeycloakSecurityContext ksc = (KeycloakSecurityContext)session.getAttribute(KeycloakSecurityContext.class.getName());
    // KeycloakSecurityContextから、IDTokenを取得
    IDToken idToken = ksc.getIdToken();
%>

PREFERRED_USERNAME : <%=idToken.getPreferredUsername()%><br>
EMAIL: <%=idToken.getEmail() %><br>
GIVEN_NAME: <%=idToken.getGivenName()%><br>
FAMILY_NAME: <%=idToken.getFamilyName()%><br>
  1. http://kc-tomcat.example.com:8080/examples/getUserInfo.jsp にアクセスします。
  2. Keycloakに未ログインであるため、ログイン画面にリダイレクトが発生します。
  3. userロールを持つユーザーのID/PWでログインします。
  4. http://kc-tomcat.example.com:8080/examples/getUserInfo.jsp が表示されます。
  5. HTTPセッションからKeycloakのユーザー情報が取得できるのが分かります。 tomcat08.png

まとめ

今回はKeycloakとTomcat上のアプリケーションをID連携させる方法を確認しました。Tomcatとの連携に関しては、WAR内の設定ファイルを3つ追加/変更をするだけなので、比較的容易に組み込みが可能なクライアント・アダプターかと思います。

ただ、連携が必要なアプリケーションサーバーが多数ある場合や、そのプラットフォームが多種多様である場合は、それぞれのサーバーで導入/設定を実施していく必要があるので、作業が煩雑になる可能性があります。

このような構成の場合は、8日目の記事で私が解説する「Keycloakでリバプロ型構成を組んでみる(mod_auth_openidc編)」を利用したほうがよいかもしれません。

参考資料

脚注


  1. Keycloakサーバーとのssl接続で自己署名サーバー証明書を利用する場合にはクライアント・アダプター側のJavaのtruststoreにサーバー証明書の取り込みが必要です。(クライアント・アダプターが、Keycloakサーバーと直接SSL通信するため) 

21
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
10