Keycloakと外部IdP間のHTTPS通信をデバッグする

# はじめに
Keycloakでは、アイデンティティブローカリング機能（Keycloakでの認証をGitHubなどの外部IdPに委任する機能）などで、Keycloakと外部システムが直接HTTPS通信をするケースがあります。
このようなケースでHTTPS通信内容をデバッグしたい場合、tcpdumpなどでキャプチャするのが一般的だと思いますが、現場から離れているとtcpdumpのコマンドやキャプチャ結果の確認方法を忘れてしまいます:sweat:

そのため、本記事ではそんなエンジニアでも簡単にGUIからHTTPS通信内容をデバッグできる方法を備忘を兼ねて残しておきます。

# 環境前提
Keycloakの動作環境は以下とします。Windows環境のlocalhostで動作させる前提です。

| 分類 | プロダクト・バージョン |
|:-|:-|
| OS | Windows 11 |
| JDK | OpenJDK 21.0.4(MS Build) |
| Keycloak | 26.0.1 |

また、手順中で利用するソフトウェアは以下のとおりです（予めインストールしておくと良いと思います）。

| プロダクト | バージョン | 用途 |
|:-|:-|:-|
| [Fiddler Classic](https://www.telerik.com/download/fiddler) | v5.0.20244.10953 | HTTPS通信の終端、プロキシ、通信内容の可視化 |
| [OpenSSL](https://slproweb.com/products/Win32OpenSSL.html) | OpenSSL 3.3.2 3 Sep 2024 | 証明書の変換（cer→pem） |

# どのHTTPS通信を解析するの？
Keycloakのログイン画面からGitHub（外部IdP）のログイン画面に遷移し、GitHub側でログインした際にKeycloakとGitHubで通信される内容を解析してみようと思います。

![github_login.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/4d61c289-1143-b204-d237-8f5708083d7a.gif)

:::note info
なお、本記事では、KeycloakにおいてGitHubで外部IdP認証を行う方法については触れません。
下記のQiita記事が詳しいですので、こちらをご参照ください。
https://qiita.com/suin/items/cb60e903eb1ddb15719b

（Keycloakの青本にもGitHubで外部IdP認証を行う方法を執筆していますので、気になる方はこちらもチェックをお願いします…）
https://www.ric.co.jp/book/new-publication/detail/2081
:::

Identity Brokeringの処理フローで言うところの、下図の「7. Authentication Response」に相当する箇所の通信を解析します。
Identity Brokerが`Keycloak`、Identity Providerが`GitHub`に相当します。
（GitHubの場合、7.は単純なレスポンスだけではなく、KeycloakからUser情報取得APIもコールされます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/d9c1f35b-5b79-75e5-3ffe-93efd1067da3.png)


# Fiddler ClassicでHTTPS通信を復号する
Fiddler Classicは、HTTP/HTTPS通信のキャプチャに特化したトラフィック解析ツールです。

https://www.telerik.com/download/fiddler

:::note info
インストール方法などは参考となるQiita記事がいくつかありますので、そちらをご参照ください。
https://qiita.com/nt-7/items/c897e9460ef43af6ed14
:::

まず、Fiddler ClassicでHTTPS通信を復号する設定を適用します。
Fiddler Classicの起動後、`Tools → Options...`を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/1aee059e-5c79-5488-1929-4991ad33532f.png)

ダイアログが開くので、`HTTPS`タブの`Decrypt HTTPS traffic`と`Ignore server certificate errors`にチェックを入れてOKをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/9062dee0-4888-a3ab-b52a-b77ba2e3fdac.png)

途中、ダイアログが表示されますが、こちらも`Yes`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/6447c1a7-7de5-5b46-38bd-1ad308bcff63.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/e26effdc-12b1-e1ee-3923-2a9a33a21a73.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/9b25b788-d7cf-9133-55a0-ad845fde0e82.png)



この時点で、EdgeなどのブラウザからインターネットへのHTTPS通信は復号されるようになり、Fiddler Classic上で通信内容を確認することができます。

試しにGoogle検索で「Keycloak」と検索した時のFiddler Classicの様子がこちらです。Edgeのプロセスでレスポンスの内容が見えていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/9f57dc57-1b2b-df62-130d-2cff36697a58.png)


HTTPS通信内容を表示できるのは、Fiddler Classicでパケットキャプチャしている間はOSのプロキシ設定にFiddler Classicが適用され、Fiddler ClassicでHTTPS通信を復号しているためです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/8969204c-27b9-939b-1830-ca0d26e2cc4e.png)

但し、Javaアプリケーション（Keycloak）は自動でFiddler Classicをプロキシして通信してくれません（下図のイメージ）。
そのため、手動でFiddler Classicをプロキシするよう設定する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/450f8af5-fcbb-62fe-f2b6-2119f89ff672.png)

# Fiddler Classicからルート証明書をエクスポート・変換する
ここからはKeycloakのHTTPS通信内容を解析する手順を説明します。
ブラウザ以外のHTTPS通信を解析するケースを想定してか、Fiddler Classicではルート証明書をエクスポートできるようになっています。
先ほど利用したダイアログの`HTTPS`タブから`Actions`ボタンをクリックし、`Export Root Certificate to Desktop`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/94db0e7f-b29b-8ac4-8f9f-f0e3abbe56d2.png)

すると、デスクトップに`FiddlerRoot.cer`がエクスポートされます。

証明書をJavaアプリケーション（Keycloak）で読み込めるよう、cerからpemに変換します。変換にはOpenSSLを利用します。
```
openssl x509 -inform der -in FiddlerRoot.cer -out FiddlerRoot.pem
```
これで、`FiddlerRoot.pem`ができあがりました。

# Keycloakのトラストストアのディレクトリに証明書を配置する

KeycloakがFiddler Classicのルート証明書を認識できるよう、適切な場所に`FiddlerRoot.pem`を配置する必要があります。
Keycloakでは、`[Keycloakのホームディレクトリ]/conf/truststores`配下に`FiddlerRoot.pem`を配置しておくと、起動時に自動で読み込まれます。

:::note
なお、証明書の配置先ディレクトリは、Keycloakの`truststore-paths`オプションから指定することもできます。
https://www.keycloak.org/server/keycloak-truststore#_configuring_the_system_truststore
:::

# KeycloakのHTTPS通信をFiddler Classicを経由（プロキシ）させる
Keycloakでは、環境変数の`HTTP_PROXY` `HTTPS_PROXY`からプロキシサーバを指定できます。

https://www.keycloak.org/server/outgoinghttp#_proxy_mappings_for_outgoing_http_requests

そのため、Keycloakの起動前にFiddler Classicをプロキシサーバとして環境変数に設定しておきましょう。
```
set HTTP_PROXY=http://127.0.0.1:8888
set HTTPS_PROXY=http://127.0.0.1:8888
```

:::note warn
Javaアプリケーションの場合、起動時の引数やJAVA_OPTSで`-Dhttps.ProxyHost` `-Dhttps.ProxyPort`によりプロキシを指定できますが、Keycloakの場合はこれらの引数は無視され、代わりに環境変数のプロキシ設定が適用されるようです。
https://github.com/keycloak/keycloak/issues/13693
:::

以上で設定は終わりです。
これでFiddler ClassicのGUIからKeycloak・外部IdP間のHTTPS通信内容を確認できるようになります。
この状態で冒頭のKeycloakからGitHubへの外部IdP認証を行ってみましょう。GitHubへのリクエスト内容、GitHubからのレスポンス内容などを確認できるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116164/c2e6474c-5677-c54e-8a08-7fadc51f63f3.png)

:::note
例えば、上記画像のProcess列が「java」となっている箇所がKeycloak（Javaアプリケーション）・GitHub間の通信内容になります。
KeycloakからGitHubのユーザ取得APIが呼び出され、そのレスポンスとしてユーザ情報が返却されていることが分かります。
:::

以上で、GitHub側の属性がKeycloakに正しくマッピングされていない、といったケースで実際に通信を解析してデバッグできるようになりました。

# まとめ
今回は、Keycloakと外部IdP間のHTTP通信を解析する手順を試してみました。
知らないとやり方に迷うところもあるので、誰かの参考になれば幸いです。