株式会社 日立製作所 茂木昂士
Hostname SPI を利用するシーン
今回はKeycloak 4.3.0.Finalから登場した Hostname SPI という機能について説明します。Keycloak は自身の URL をリクエストの内容をもとに生成しています。これらの値は、/.well-konwn/openid-configurationの値やアクセストークン、ID トークンのissなどの値に利用されています。
デフォルトの設定では、リクエスト時のホスト名とスキーマの値を利用しますが、ロードバランサーなどを挟む場合にはhttp-listenerの設定にproxy-address-forwarding="true"というアトリビュートを指定します。この設定を行うと、X-Fowrarded-Proto, X-Frowarded-Forといったヘッダの値をもとに、自身の URL を生成するようになります(参考)。なお、Keycloak のコンテナイメージを利用する際、環境変数PROXY_ADDRESS_FORWARDINGにtrueを指定すると、同じように設定を行うことができます。
通常はこれらの設定で十分なのですが、下記のようなケースで問題が出てきます。
- ロードバランサーの内側では内部的な Host 名でアクセスしたい
- Keycloak とアプリケーションが同一サーバで動いているため、localhost でアクセスしたい
- Kubernetes 等を利用しているので、クラスタ内部の Service 経由(~.svc.cluster.local など)でアクセスしたい
上記のような場合、ネットワークの内部と外部で Keycloak の URL が異なってしまいます。
この様な状態だと、例えば ID トークン、アクセストークンのバリデーションを行った際にissの値が異なるためエラーとなる、Token Introspection を行った際も無効なトークンとして扱われてしまうなどといった問題が発生します。
「アクセストークンが正しく発行できているのにリクエストがエラーになる」となっていると、大抵この問題を踏んでいたりします。
Hostname SPI を利用することで、Keycloak の URL を柔軟に変更することができるようになり、これらの問題を回避することができるようになります。
Hostname SPI の概要
Hostname SPI は名前の通り、Keycloak の Hostname を設定するためのService Provider Interface(SPI: Keycloak をカスタマイズするために提供されているインターフェース)です。Keycloak 4.3.0.Finalでは、このインターフェースを実装したRequestHostnameProviderおよびFixedHostnameProviderが提供されています。
RequestHostnameProviderはこれまで同様、リクエストの値をもとにして Keycloak の URL を生成します。一方FixedHostnameProviderは、常にプロパティーで設定した値をもとに Keycloak の URL を生成します。FixedHostnameProviderに指定できるプロパティーとしては、hostname,httpPort,httpsPortがあり、さらに4.6.0.FinalではalwaysHttpsというプロパティーも追加されました。
また、HostnameProviderというインターフェースを実装すれば、独自にカスタマイズすることが可能です。
Hostname SPI の設定方法と確認方法
RequestHostnameProvider, FixedHostnameProviderのどちらを利用するか、およびFixedHostnameProviderのプロパティーは Keycloak の設定ファイル(standalone.xml, standalone-ha.xmlなど) で設定します。
今回はFixedHostnameProviderを利用するため、下記のように設定しました。
<spi name="hostname">
<default-provider>fixed</default-provider>
<provider name="fixed" enabled="true">
<properties>
<property name="hostname" value="keycloak.external.net"/>
<property name="httpPort" value="80"/>
<property name="httpsPort" value="443"/>
<property name="alwaysHttps" value="true"/>
</properties>
</provider>
</spi>
この設定を行った状態で Keycloak を起動し、http://localhost:8080/auth/realms/master/.well-known/openid-configurationにアクセスすると、下記のようにissuerや各 Endpoint の URL が Hostname SPI で指定した値になります。
{
"issuer": "https://keycloak.external.net/auth/realms/master",
"authorization_endpoint": "https://keycloak.external.net/auth/realms/master/protocol/openid-connect/auth",
"token_endpoint": "https://keycloak.external.net/auth/realms/master/protocol/openid-connect/token",
"token_introspection_endpoint": "https://keycloak.external.net/auth/realms/master/protocol/openid-connect/token/introspect",
...
}
まとめ
この様に Hostname SPI を利用すると、Keycloak の URL を固定化するなど柔軟に設定を行うことができるようになります。issの値が違う、などの問題が出た際にはこの機能を利用してみてください。
