OpenID Connect(OIDC)ベアラートークン認証によるサービスアプリケーションの保護
Quarkus OpenID Connect (OIDC) エクステンションを使用して、Bearer トークン認証で Jakarta REST アプリケーションを保護します。 ベアラートークンは、OIDC および OAuth 2.0 準拠の認可サーバー (Keycloak など) によって発行されます。
OIDC ベアラートークン認証の詳細は、Quarkus の OpenID Connect (OIDC) ベアラートークン認証 ガイドを参照してください。
OIDC 認可コードフロー認証を使用して Web アプリケーションを保護する場合は、Web アプリケーションを保護するための OpenID Connect 認可コードフローメカニズム ガイドを参照してください。
要件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
動作するコンテナランタイム(Docker, Podman)
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
アーキテクチャー
この例では、2 つのエンドポイントを提供するシンプルなマイクロサービスをビルドする方法を示します。
-
/api/users/me
-
/api/admin
これらのエンドポイントは保護されており、クライアントがリクエストとともにベアラートークンを送信した場合にのみアクセスできます。ベアラートークンは有効 (署名、有効期限、audience など) であり、マイクロサービスによって信頼されている必要があります。
Keycloak サーバーはベアラートークンを発行し、トークンが発行されたサブジェクトを表します。 これは OAuth 2.0 認可サーバーであるため、トークンはユーザーに代わって動作するクライアントも参照します。
有効なトークンを持つすべてのユーザーは、/api/users/me
エンドポイントにアクセスできます。
レスポンスとして、トークンの情報から取得したユーザーの詳細を含む JSON ドキュメントを返します。
/api/admin
エンドポイントは RBAC (ロールベースのアクセス制御) で保護されており、admin
ロールを持つユーザーのみがアクセスできます。
このエンドポイントでは、@RolesAllowed
アノテーションを使用して、アクセス制約を宣言的に適用します。
ソリューション
次のセクションの指示に従って、アプリケーションを段階的に作成します。 完成した例に直接進むこともできます。
git clone https://github.com/quarkusio/quarkus-quickstarts.git
コマンドを実行して Git リポジトリーをクローンできます。または、https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip[アーカイブ] をダウンロードできます。
ソリューションは、security-openid-connect-quickstart
ディレクトリー にあります。
Maven プロジェクトの作成
oidc
エクステンションを使用して新しい Maven プロジェクトを作成することも、既存の Maven プロジェクトにエクステンションを追加することもできます。
次のいずれかのコマンドを実行します。
新しい Maven プロジェクトを作成するには、次のコマンドを使用します。
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=security-openid-connect-quickstart"
If you already have your Quarkus project configured, you can add the oidc
extension to your project by running the following command in your project base directory:
quarkus extension add oidc
./mvnw quarkus:add-extension -Dextensions='oidc'
./gradlew addExtension --extensions='oidc'
これにより、ビルドファイルに次の内容が追加されます。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
implementation("io.quarkus:quarkus-oidc")
アプリケーションの記述
-
次の例に示すように、通常の Jakarta REST リソースである
/api/users/me
エンドポイントを実装します。package org.acme.security.openid.connect; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import org.jboss.resteasy.reactive.NoCache; import io.quarkus.security.identity.SecurityIdentity; @Path("/api/users") public class UsersResource { @Inject SecurityIdentity securityIdentity; @GET @Path("/me") @RolesAllowed("user") @NoCache public User me() { return new User(securityIdentity); } public static class User { private final String userName; User(SecurityIdentity securityIdentity) { this.userName = securityIdentity.getPrincipal().getName(); } public String getUserName() { return userName; } } }
-
次の例に示すように、
/api/admin
エンドポイントを実装します。package org.acme.security.openid.connect; import jakarta.annotation.security.RolesAllowed; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; @Path("/api/admin") public class AdminResource { @GET @RolesAllowed("admin") @Produces(MediaType.TEXT_PLAIN) public String admin() { return "granted"; } }
この例の主な違いは、
admin
ロールを付与されたユーザーのみがエンドポイントにアクセスできることを確認する際に、@RolesAllowed
アノテーションが使用される点です。
SecurityIdentity
のインジェクションは、 @RequestScoped
と @ApplicationScoped
の両方のコンテキストでサポートされています。
アプリケーションの設定
-
src/main/resources/application.properties
ファイルで次の設定プロパティーを設定して、Quarkus OpenID Connect (OIDC) エクステンションを設定します。%prod.quarkus.oidc.auth-server-url=http://localhost:8180/realms/quarkus quarkus.oidc.client-id=backend-service quarkus.oidc.credentials.secret=secret # Tell Dev Services for Keycloak to import the realm file # This property is not effective when running the application in JVM or native modes quarkus.keycloak.devservices.realm-path=quarkus-realm.json
以下の場合:
-
%prod.quarkus.oidc.auth-server-url
は、OpenID Connect (OIDC) サーバーのベース URL を設定します。%prod.
プロファイル接頭辞により、アプリケーションを開発 (dev) モードで実行する際に、Dev Services for Keycloak
がコンテナーを起動するようになります。 詳細は、アプリケーションを開発モードで実行する セクションを参照してください。 -
quarkus.oidc.client-id
は、アプリケーションを識別するクライアント ID を設定します。 -
quarkus.oidc.credentials.secret
は、client_secret_basic
認証方法で使用されるクライアントシークレットを設定します。
詳細は、Quarkus の OpenID Connect (OIDC) 設定プロパティー ガイドを参照してください。
Keycloakサーバーの起動と設定
-
レルム設定ファイル をクラスパス (
target/classes
ディレクトリー) に配置し、開発モードで実行する際に自動的にインポートされるようにします。 すでに 完全なソリューション をビルド済みの場合は、このレルムファイルはビルド時にクラスパスに追加されるため、この手順は必要ありません。アプリケーションを開発モードで実行するときは、Keycloak サーバーを起動しないでください。
Dev Services for Keycloak
がコンテナーを起動します。 詳細は、アプリケーションを開発モードで実行する セクションを参照してください。 -
Keycloak サーバーをが起動するには、Docker を使用して次のコマンドを実行します。
docker run --name keycloak -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin -p 8180:8080 quay.io/keycloak/keycloak:{keycloak.version} start-dev
-
keycloak.version
がバージョン26.1.3
以降に設定されている場合。
-
-
Keycloak サーバーには localhost:8180 からアクセスできます。
-
Keycloak 管理コンソールにアクセスするには、次のログイン認証情報を使用して
admin
ユーザーとしてログインします。-
ユーザー名:
admin
-
パスワード:
admin
-
-
新しいレルムを作成するには、アップストリームコミュニティーリポジトリーから レルム設定ファイル をインポートします。
詳細は、Keycloak ドキュメントの 新しいレルムの作成と設定 を参照してください。
Keycloak Admin Client を使用してアプリケーションから Keycloak サーバーを設定するには、セットアップに基づいて次のいずれかのエクステンションを含めます。
これらのガイドラインは、REST サーバー、REST クライアント、またはその両方で作業しているかどうかに関係なく、Keycloak Admin Client と REST フレームワークをシームレスに統合できるようにします。 詳細は、Quarkus Keycloak Admin Client ガイドを参照してください。 |
アプリケーションを開発モードで実行する
-
開発モードでアプリケーションを実行するには、次のコマンドを実行します。
CLIquarkus dev
Maven./mvnw quarkus:dev
Gradle./gradlew --console=plain quarkusDev
-
Dev Services for Keycloak は、Keycloak コンテナーを起動し、
quarkus-realm.json
をインポートします。
-
-
/q/dev-ui にある Dev UI を開きます。 次に、
OpenID Connect
カードで、Keycloak provider
リンクをクリックします。 -
OpenID Connect Dev UI
によって提供されるSingle Page Application
にログインするように求められたら、次の手順を実行します。-
user
ロールを持つalice
(パスワード:alice
) としてログインします。-
/api/admin
にアクセスすると、ステータスコード403
が返されます。 -
/api/users/me
にアクセスすると、ステータスコード200
が返されます。
-
-
ログアウトし、
admin
とuser
の両方のロールを持つadmin
(パスワード:admin
) として再度ログインします。-
/api/admin
にアクセスすると、ステータスコード200
が返されます。 -
/api/users/me
にアクセスすると、ステータスコード200
が返されます。
-
-
JVM モードでアプリケーションを実行する
開発モードが完了したら、アプリケーションを標準の Java アプリケーションとして実行できます。
-
アプリケーションをコンパイルします。
CLIquarkus build
Maven./mvnw install
Gradle./gradlew build
-
アプリケーションを実行します。
java -jar target/quarkus-app/quarkus-run.jar
ネイティブモードでアプリケーションを実行する
この同じデモを、変更を加えずにそのままネイティブモードにコンパイルできます。 これは、実稼働環境に JVM をインストールする必要がなくなることを意味します。 ランタイムテクノロジーは生成されたバイナリーに組み込まれ、必要最小限のリソースで実行できるように最適化されています。
コンパイルには少し時間がかかるため、この手順はデフォルトで無効になっています。
-
native
プロファイルを有効にして、アプリケーションを再度ビルドします。CLIquarkus build --native
Maven./mvnw install -Dnative
Gradle./gradlew build -Dquarkus.native.enabled=true
-
しばらく待ってから、次のバイナリーを直接実行します。
./target/security-openid-connect-quickstart-1.0.0-SNAPSHOT-runner
アプリケーションのテスト
開発モードでのアプリケーションのテストの詳細は、前述のアプリケーションを開発モードで実行する セクションを参照してください。
curl
を使用して、JVM またはネイティブモードで起動したアプリケーションをテストできます。
-
アプリケーションはベアラートークン認証を使用するため、アプリケーションリソースにアクセスするには、まず Keycloak サーバーからアクセストークンを取得する必要があります。
export access_token=$(\
curl --insecure -X POST http://localhost:8180/realms/quarkus/protocol/openid-connect/token \
--user backend-service:secret \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'username=alice&password=alice&grant_type=password' | jq --raw-output '.access_token' \
)
|
上記の例では、ユーザー alice
のアクセストークンを取得します。
-
どのユーザーも
http://localhost:8080/api/users/me
エンドポイントにアクセスでき、ユーザーの詳細を含む JSON ペイロードが返されます。
curl -v -X GET \
http://localhost:8080/api/users/me \
-H "Authorization: Bearer "$access_token
-
admin
ロールを持つユーザーのみがhttp://localhost:8080/api/admin
エンドポイントにアクセスできます。 以前に発行されたアクセストークンを使用してこのエンドポイントにアクセスしようとすると、サーバーから403
レスポンスが返されます。
curl -v -X GET \
http://localhost:8080/api/admin \
-H "Authorization: Bearer "$access_token
-
管理エンドポイントにアクセスするには、
admin
ユーザーのトークンを取得します。
export access_token=$(\
curl --insecure -X POST http://localhost:8180/realms/quarkus/protocol/openid-connect/token \
--user backend-service:secret \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'username=admin&password=admin&grant_type=password' | jq --raw-output '.access_token' \
)
Dev Services for Keycloak
に依存するインテグレーションテストの作成に関する詳細は、「OpenID Connect (OIDC) ベアラートークン認証」ガイドの Dev Services for Keycloak セクションを参照してください。