Protect a service application by using OpenID Connect (OIDC) Bearer token authentication
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 11+ がインストールされ、
JAVA_HOMEが適切に設定されていること -
Apache Maven 3.9.3
-
動作するコンテナランタイム(Docker, Podman)
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
アーキテクチャ
この例では、2 つのエンドポイントを提供するシンプルなマイクロサービスをビルドする方法を示します。
-
/api/users/me -
/api/admin
これらのエンドポイントは保護されており、クライアントがリクエストとともにベアラートークンを送信した場合にのみアクセスできます。ベアラートークンは有効 (署名、有効期限、audience など) であり、マイクロサービスによって信頼されている必要があります。
The bearer token is issued by a Keycloak server and represents the subject for which the token was issued. Because it is an OAuth 2.0 Authorization server, the token also references the client acting on the user’s behalf.
有効なトークンを持つすべてのユーザーは、/api/users/me エンドポイントにアクセスできます。
レスポンスとして、トークンの情報から取得したユーザーの詳細を含む JSON ドキュメントを返します。
/api/admin エンドポイントは RBAC (ロールベースのアクセス制御) で保護されており、admin ロールを持つユーザーのみがアクセスできます。
このエンドポイントでは、@RolesAllowed アノテーションを使用して、アクセス制約を宣言的に適用します。
ソリューション
次のセクションの指示に従って、アプリケーションを段階的に作成します。 完成した例に直接進むこともできます。
git clone -b 3.2 https://github.com/quarkusio/quarkus-quickstarts.git コマンドを実行して Git リポジトリーをクローンできます。または、https://github.com/quarkusio/quarkus-quickstarts/archive/3.2.zip[アーカイブ] をダウンロードできます。
ソリューションは、security-openid-connect-quickstart ディレクトリー にあります。
手順
.1. Maven プロジェクトの作成
oidc エクステンションを使用して新しい Maven プロジェクトを作成することも、既存の Maven プロジェクトにエクステンションを追加することもできます。
次のいずれかのコマンドを実行します。
新しい Maven プロジェクトを作成するには、次のコマンドを使用します。
すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリーで以下のコマンドを実行することで、プロジェクトに oidc エクステンションを追加することができます。
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")
1. アプリケーションの記述
-
次の例に示すように、通常の 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; } } } -
Implement the
/api/adminendpoint as shown in the following simple example: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 の両方のコンテキストでサポートされています。
1.1. アプリケーションの設定
-
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-urlsets the base URL of the OpenID Connect (OIDC) server. The%prod.profile prefix ensures thatDev Services for Keycloaklaunches a container when you run the application in development (dev) mode. For more information, see the Run the application in dev mode section. -
quarkus.oidc.client-idsets a client-ID that identifies the application. -
quarkus.oidc.credentials.secretは、client_secret_basic認証方法で使用されるクライアントシークレットを設定します。
詳細は、Quarkus の OpenID Connect (OIDC) 設定プロパティー ガイドを参照してください。
1.2. Keycloakサーバーの起動と設定
-
レルム設定ファイル をクラスパス (
target/classesディレクトリー) に配置し、開発モードで実行する際に自動的にインポートされるようにします。 すでに 完全なソリューション をビルド済みの場合は、このレルムファイルはビルド時にクラスパスに追加されるため、この手順は必要ありません。Do not start the Keycloak server when you run the application in dev mode;
Dev Services for Keycloakwill start a container. For more information, see the Run the application in dev mode section. -
Keycloak サーバーをが起動するには、Docker を使用して次のコマンドを実行します。
docker run --name keycloak -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -p 8180:8080 quay.io/keycloak/keycloak:{keycloak.version} start-dev-
Where the
keycloak.versionis set to version17.0.0or later.
-
-
Keycloak サーバーには localhost:8180 からアクセスできます。
-
To access the Keycloak Administration Console, log in as the
adminuser by using the following login credentials:-
ユーザー名:
admin -
パスワード:
admin
-
-
新しいレルムを作成するには、アップストリームコミュニティーリポジトリーから レルム設定ファイル をインポートします。
For more information, see the Keycloak documentation about creating a new realm.
|
If you want to use the Keycloak Admin Client to configure your server from your application, you need to include either the |
1.3. アプリケーションを開発モードで実行する
-
開発モードでアプリケーションを実行するには、次のコマンドを実行します。
CLIquarkus devMaven./mvnw quarkus:devGradle./gradlew --console=plain quarkusDev-
Dev Services for Keycloak will start a Keycloak container and import a
quarkus-realm.json.
-
-
Open a Dev UI, which you can find at /q/dev-v1, then click a
Provider: Keycloaklink in anOpenID ConnectDev UIcard. -
OpenID Connect Dev UIによって提供されるSingle Page Applicationにログインするように求められたら、次の手順を実行します。-
userロールを持つalice(パスワード:alice) としてログインします。-
Accessing
/api/adminreturns403. -
Accessing
/api/users/mereturns200.
-
-
Log out and log in as
admin(password:admin), who has bothadminanduserroles.-
Accessing
/api/adminreturns200. -
Accessing
/api/users/mereturns200.
-
-
1.4. JVM モードでアプリケーションを実行する
開発モードが完了したら、アプリケーションを標準の Java アプリケーションとして実行できます。
-
アプリケーションをコンパイルします。
CLIquarkus buildMaven./mvnw installGradle./gradlew build -
アプリケーションを実行します。
java -jar target/quarkus-app/quarkus-run.jar
1.5. ネイティブモードでアプリケーションを実行する
You can compile this same demo as-is into native mode without needing any modifications. This implies that you no longer need to install a JVM on your production environment. The runtime technology is included in the produced binary and optimized to run with minimal resources required.
コンパイルには少し時間がかかるため、この手順はデフォルトで無効になっています。
-
nativeプロファイルを有効にして、アプリケーションを再度ビルドします。CLIquarkus build --nativeMaven./mvnw install -DnativeGradle./gradlew build -Dquarkus.package.type=native -
しばらく待ってから、次のバイナリーを直接実行します。
./target/security-openid-connect-quickstart-1.0.0-SNAPSHOT-runner
1.6. アプリケーションのテスト
For information about testing your application in dev mode, see the preceding Run the application in dev mode section.
curl を使用して、JVM またはネイティブモードで起動したアプリケーションをテストできます。
-
Because the application uses Bearer token authentication, you first need to obtain an access token from the Keycloak server to access the application resources:
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' \
)
For information about writing integration tests that depend on Dev Services for Keycloak, see the Dev Services for Keycloak section of the "OpenID Connect (OIDC) Bearer token authentication" guide.