株式会社 日立製作所 茂木昂士
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
の値が違う、などの問題が出た際にはこの機能を利用してみてください。