Keycloak を活用した OIDC 開発環境の構築と SpringBoot 連携手順

# はじめに

Spring Boot で OpenID Connect (以下、OIDC) によるソーシャルログイン機能を実装する場合、OIDC プロバイダーの適切な設定は不可欠です。正しく構成されていないと、アプリケーションを正常に起動することができなくなってしまいます。

たとえば、GitHub からプロジェクトをクローンしてローカル環境で動作させる場合、クライアントシークレットなどの機密情報を共有するのはセキュリティ上のリスクが高く、現実的ではありません。一方で、各開発者が個別に OIDC プロバイダーにアプリケーションを登録するのも手間もかかります。そもそも、柔軟性やコスト面から本番用の OIDC プロバイダーを利用するのが好ましくない場合もあります。

Keycloak を開発環境用の OIDC プロバイダーとして代用する方法を試したところ、比較的簡単に実装できたので、本記事ではその具体的な手順を紹介します。

# 環境

- Docker: 24.0.5
  - Docker Desktop: 4.33.1
  - Docker Compose: 2.20.2-desktop.1
- Keycloak: 25.0.1（Docker コンテナとして実行）
- Spring Boot: 3.3.3
- Java: OpenJDK 17
- Gradle: 8.8
- Windows 11 Pro

# Keycloak ついて

Keycloak は、ユーザーの認証やアクセス管理を行うオープンソースのツールです。

シングルサインオン（SSO）、ID ブローカー、ソーシャルログイン、ユーザーフェデレーションなどの多くの機能を提供し、管理コンソールを通じてこれらの設定を直感的に行えるのが大きな特徴です。

# 構築する開発環境について

多様な機能を持つ Keycloak ですが、今回は開発環境用の OIDC プロバイダーとして利用します。

また、Keycloak はローカルに直接インストールすることも可能ですが、今回は移植性を高めるために Docker コンテナで稼働させます。ただし、Keycloak の設定情報はコンテナを削除するときに失われてしまうため、事前にエクスポートしてプロジェクトに含めておきます。

これにより、GitHub からプロジェクトをクローンしたあとに、即座にアプリケーションの立ち上げが可能な状態を実現します。

# 環境構築

Keycloak の設定情報エクスポートから実際の開発環境でのセットアップまでを段階的に解説し、最後に Spring Boot アプリケーションと Keycloak の連携方法について簡単に紹介します。

なお、以下の手順は Spring Boot アプリケーションのプロジェクトルートで行うことを想定しています。ディレクトリの指定は、適宜プロジェクト構成に合わせて変更してください。

## 1. 設定情報エクスポート専用の Keycloak コンテナ起動

はじめに、Keycloak 設定情報をエクスポートするために使うコンテナを起動します。
Spring Boot アプリケーションのプロジェクトルートで以下のコマンドを実行してください。

```bash
docker run -dit \
  --name keycloak-export \
  --mount type=bind,src="$(pwd)"/docker/keycloak/data/import,target=/opt/keycloak/data/export \
  -p 18080:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:25.0.1 start-dev
```

**オプション説明**

- **`--mount type=bind,src="$(pwd)"/docker/keycloak/data/import,target=/opt/keycloak/data/export`**
  コンテナ内にエクスポートされた設定ファイルをホストマシン上に保存します。どちらのディレクトリも必要に応じて変更可能です。
  ※ `"$(pwd)"` は、現在の作業ディレクトリ（つまり、Spring Boot アプリケーションのプロジェクトルート）を表します。

- **`-p 18080:8080`**
  ホストの 18080 ポートをコンテナの 8080 ポートにマッピングします。
  8080 ポートは、Spring Boot アプリケーションのポートと重複する可能性があるため、必要に応じてポート番号を変更します。

- **`-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin`**
  管理者ユーザーのユーザー名とパスワードを設定します。管理コンソールにログインする際に使用します。

- **`start-dev`**
  Keycloak を開発モードで起動します。

## 2. Keycloak における認証環境の設定

つぎは、Keycloak 管理コンソールで OIDC を利用した認証に必要な設定を行っていきます。

まず、ブラウザを開いて http://localhost:18080 にアクセスしてください。
Keycloak のログイン画面が表示されたら、先ほど設定した管理者ユーザー名（admin）とパスワード（admin）でログインします。

![oauth2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/2dd9fd4e-4499-f4d2-c612-0b8afa57a0ab.png)

ログインすると、Keycloak 管理コンソールが表示されます。初期設定では、デフォルトの master レルムが選択されています。

![oauth2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/a599ed23-7c4d-3f73-283e-cbbbc8b6c7fe.png)

**レルム (Realm)** とは、Keycloak においてユーザー、認証、セッション管理、アクセスコントロールなど、セキュリティ関連の情報を管理する単位です。
今回の場合、単一の OIDC プロバイダーの設定が適用される範囲と考えると理解しやすいでしょう。

デフォルトで存在する master レルムは、Keycloak 全体を管理するための特別なレルムです。通常、アプリケーションを管理するレルムとしては使用しないため、新しくレルムを作成する必要があります。

### 2.1. レルム作成

以下の手順に従って、新しいレルムを作成しましょう。

**1. 画面左上部のドロップダウンメニューから、[Create realm] ボタンを選択します。**

![oauth2_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/aa755cc1-3bac-8f01-ceb2-10f7920dcaba.png)

**2. Realm name フィールドに `mykeycloak` と入力し、[Create] ボタンをクリックします。**

![oauth2_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/767330b2-faa7-147b-9635-d11a42220eb8.png)

新しく作成されたレルムの画面が表示されたら作成完了です。

以降の操作は、この mykeycloak レルム内で行っていきます。

### 2.2. ユーザー作成

つぎは、mykeycloak レルムにユーザーを追加します。

以下の手順に従ってください。

**1. 左側のメニューから [Users] を選択します。**

**2. [Create new user] ボタンをクリックします。**

![oauth2_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/96257592-9f11-33f4-93b7-111a665f4d2f.png)

**3. フォームに以下の情報を入力し、[Create] ボタンをクリックします。**

- **Username**: `user`
- **Email**: 任意のメールアドレス
- **First name**: 任意の名前
- **Last name**: 任意の姓

![oauth2_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/83f2ec6a-cdf6-3cdd-0a72-380963f3d24d.png)

ユーザーが作成されると、そのユーザーの詳細情報ページに移動します。
このユーザーを使ってログインできるようにするために、パスワードの設定も行います。

**1. 上部の [Credentials] タブを選択します。**

**2. [Set Password] ボタンをクリックします。**

![oauth2_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/9e97438f-35c5-4265-45f3-2329a9eedbdc.png)

**3. パスワードを入力し、Temporary フィールドを Off に切り替えます。**

![oauth2_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/122fe86d-34d0-c03b-d03c-90a554810f65.png)

**4. [Save] ボタンをクリックします。**

※ Temporary フィールドは、ユーザーが最初のログイン時にこのパスワードを更新する必要がないようにオフに切り替えます。

### 2.3. クライアント作成

つぎは、Spring Boot アプリケーションをクライアントとして登録します。

以下の手順に従って設定を行ってください。

**1. 左側のメニューから [Clients] を選択します。**

**2. [Create client] ボタンをクリックします。**

![oauth2_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/00c8ebaf-3923-5d36-5e8d-1100a74b5375.png)

**3. フォームに以下の情報を入力し、[Next] ボタンをクリックします。**

- **Client type**: `OpenID Connect`
- **Client ID**: `myclient`

![oauth2_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/49aa1b97-0f5c-24ad-a94f-bd9a535440c9.png)

**4. Client authentication を On に切り替え、[Next] ボタンをクリックします。**

![oauth2_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/5ce60636-ad85-af28-6f37-0c181620f3bf.png)

**5. Valid redirect RUIs フィールドに `http://localhost:8080/*` と入力し、[Save] ボタンをクリックします。**

![oauth2_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/2aedca94-627c-6227-bd23-04b4c1d2313b.png)

リダイレクト URI には、Spring Boot アプリケーションが 8080 ポートで実行される想定で、`http://localhost:8080/*` を指定しています。

レルムやユーザーの設定が Keycloak 固有であるのに対し、クライアントの作成 (アプリケーションの登録) は、一般的な OIDC プロバイダーでも必要となる標準的な設定です。

これで、Spring Boot アプリケーションにおいて、Keycloak を OIDC プロバイダーとして利用できるようになりました。

## 3. Keycloak の設定情報エクスポート

設定が完了したので、つぎはこの情報を JSON ファイルとしてエクスポートします。

エクスポートは Keycloak 管理コンソールからも可能ですが、ユーザー情報も含めてエクスポートするためにコマンドラインを使用します。

まず、以下のコマンドを実行して、実行中の Keycloak コンテナに接続してください。

```bash
docker exec -it keycloak-export /bin/bash
```

コンテナ内のシェルに入ったら、以下のコマンドを実行します。

```bash
/opt/keycloak/bin/kc.sh export --dir /opt/keycloak/data/export --users realm_file
```

**オプション説明**

- **`--dir /opt/keycloak/data/export`**
  設定ファイルのエクスポート先ディレクトリを指定します。このディレクトリはコンテナの起動時にマウントしたコンテナ側のディレクトリと一致させる必要があります。

- **`--users realm_file`**
  ユーザー情報をエクスポートする方法を指定します。今回は、ユーザー情報をレルム設定と同じファイルに含めます。

エクスポートが正常に終了すると、Spring Boot アプリケーションプロジェクトの `/docker/keycloak/data/import` ディレクトリには、以下のようなファイルが作成されています。

![oauth2_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/31dc4fb5-33bc-379f-9fd1-ba671b0c25e5.png)

このファイルは、後ほど説明する開発環境向けの Keycloak コンテナで使用します。

コンテナ内でエクスポートが完了したら、以下のコマンドを実行して、コンテナのシェルから抜けます。

```bash
exit
```

その後、ホスト環境に戻ったら以下のコマンドでコンテナを停止します。

```bash
docker stop keycloak-export
```

これで設定ファイルの作成は完了です。

## 4. 開発環境向け Keycloak コンテナの構築

つぎは、エクスポートした設定情報が反映された Keycloak コンテナを起動する例を示します。
Spring Boot アプリケーションのプロジェクトルートで以下のコマンドを実行してください。

```bash
docker run -d \
  --name keycloak-dev \
  --mount type=bind,src="$(pwd)"/docker/keycloak/data/import,target=/opt/keycloak/data/import \
  -p 18080:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:25.0.1 start-dev --import-realm
```

コマンドが長いため、以下のような `compose.yml` ファイルを用意してもいいかもしれません。

```yaml
services:
  keycloak:
    image: quay.io/keycloak/keycloak:25.0.1
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
    ports:
      - '18080:8080'
    volumes:
      - ./docker/keycloak/data/import:/opt/keycloak/data/import
    command: start-dev --import-realm
```

このファイルを使用する場合、以下のコマンドで Keycloak コンテナを起動します。

```bash
docker-compose up -d
```

**オプション説明**

- **`--mount type=bind,src="$(pwd)"/docker/keycloak/data/import,target=/opt/keycloak/data/import`**
  先ほどエクスポートした設定ファイルを含むディレクトリをコンテナ内のディレクトリにマウントします。

- **`start-dev --import-realm`**
  Keycloak を開発モードで起動し、マウントした `/opt/keycloak/data/import` ディレクトリから設定ファイルを自動インポートします。

これで、設定情報が反映された状態で Keycloak コンテナが立ち上がります。

設定情報が正常にインポートされているか確認してみましょう。

コンテナが正常に起動したら、ブラウザで http://localhost:18080 にアクセスして、Keycloak 管理コンソールにログインします。
設定したレルム、ユーザー、およびクライアントが存在し、各値が適切に設定されていることを確認してください。

アプリケーションの開発やテストは、この開発環境向けの Keycloak を稼働させた状態で進めていくことになります。

## 5. Spring Boot と Keycloak の連携

さいごに、Spring Boot アプリケーションで OIDC を利用した認証を実装し、Keycloak と連携させる方法について説明します。

ここでは、Keycloak の設定に関連する部分に焦点を当てます。Spring Security の設定や依存関係の追加については、Spring Boot の公式ドキュメントを参照してください。

ソースコードは、以下のリポジトリから参照できます。

https://github.com/hiroe-mkk/springboot-keycloak-tips

以下は、開発環境用プロパティファイルの設定例です。

```yaml
spring:
  security:
    oauth2:
      client: # Yahoo! JAPAN の代替として Keycloak を使用
        provider:
          yahoo:
            issuer-uri: http://localhost:18080/realms/mykeycloak
        registration:
          yahoo:
            client-id: myclient
            client-secret: <KeyCloak のクライアントシークレット>
            provider: yahoo
            scope: openid
            authorization-grant-type: authorization_code
            redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
```

**プロパティ説明**

- **`client-id`**
  Keycloak で設定したクライアント ID（myclient）を指定します。

- **`client-secret`**
  Keycloak で生成されたクライアントシークレットを指定します。この値は、Keycloak 管理コンソールの [Clients] の [Credentials] タブで確認できます。

![oauth2_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3671461/8bf1cdc5-d30f-1b21-593c-b791afd0279c.png)

- **`redirect-uri`**
  認証後のリダイレクト先 URI を指定します。`{baseUrl}` はアプリケーションのベース URL、`{registrationId}` は登録 ID（この場合は "yahoo"）に置き換えられます。
  この値は Keycloak 管理コンソールの [Clients] の [Valid Redirect URIs] に設定した値と一致させます。

- **`issuer-uri`**
  Keycloak サーバーの OIDC 設定情報を提供するエンドポイントを指定します。

このプロパティファイルでは、プロバイダー名は "yahoo" となっていますが、実際には Keycloak が OIDC プロバイダーとして機能します。これにより、ローカル環境で動作する Keycloak サーバーを使って認証を行うことができます。

**プロファイル機能について**

Spring Boot では、プロファイル機能を使うことで、アプリケーションの設定や動作を条件に応じて切り替えることができます。

たとえば、開発環境用の application-dev.yml と本番環境用の application-prod.yml を用意することで、環境変数やコマンドラインオプションを通じて適用するファイルを切り替えることが可能です。

この機能により、開発時にはローカルの Keycloak を使用し、本番環境では Yahoo! ID 連携 を利用するなど、環境に応じた柔軟な運用が実現できます。

**※ 注意**

Keycloak では多くの標準的な OIDC の動作をシミュレートできますが、各プロバイダー固有の認証フローやエラーハンドリングの挙動を完全に再現できない場合があります。

そのため、開発中は Keycloak を使用し、統合テストや最終的な本番環境への移行前には、実際に使用する OIDC プロバイダーでのテストを行うことが推奨されます。

# さいごに

本記事では、Keycloak を使用して開発環境用の OIDC プロバイダーを構築する方法を説明しました。この方法により、実際の OIDC プロバイダーの認証情報を使用せずに開発を進められ、効率的な開発環境の構築できます。

また、Keycloak は豊富な設定オプションを提供しており、OIDC プロバイダー固有の実装や要件を再現することも可能です。セキュリティや認証に関する機能を本番環境に近い形で検証しながら開発を進めることができるので、ぜひ試してみてください。

# 参考

▼ [Docker - Keycloak](https://www.keycloak.org/getting-started/getting-started-docker)
▼ [Importing and Exporting Realms - Keycloak](https://www.keycloak.org/server/importExport)
▼ [Spring Boot と OAuth2 - 公式サンプルコード (pleiades.io)](https://spring.pleiades.io/guides/tutorials/spring-boot-oauth2)
▼ [コア構成 :: Spring Security - リファレンスドキュメント (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/oauth2/login/core.html)
▼ [v2 - Yahoo!デベロッパーネットワーク](https://developer.yahoo.co.jp/yconnect/v2/)