OpenID Connect(OIDC)ベアラートークン認証によるサービスアプリケーションの保護
Use the Quarkus OpenID Connect (OIDC) extension to secure a Jakarta REST application with Bearer token authentication. The bearer tokens are issued by OIDC and OAuth 2.0 compliant authorization servers, such as Keycloak.
For more information about OIDC Bearer token authentication, see the Quarkus OpenID Connect (OIDC) Bearer token authentication guide.
If you want to protect web applications by using OIDC Authorization Code Flow authentication, see the OpenID Connect authorization code flow mechanism for protecting web applications guide.
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
動作するコンテナランタイム(Docker, Podman)
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
アーキテクチャ
This example shows how you can build a simple microservice that offers two endpoints:
-
/api/users/me
-
/api/admin
These endpoints are protected and can only be accessed if a client sends a bearer token along with the request, which must be valid (for example, signature, expiration, and audience) and trusted by the microservice.
A Keycloak server issues the bearer token 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.
Any user with a valid token can access the /api/users/me
endpoint.
As a response, it returns a JSON document with user details obtained from the information in the token.
The /api/admin
endpoint is protected with RBAC (Role-Based Access Control), which only users with the admin
role can access.
At this endpoint, the @RolesAllowed
annotation is used to enforce the access constraint declaratively.
ソリューション
Follow the instructions in the next sections and create the application step by step. You can also go straight to the completed example.
You can clone the Git repository by running the command git clone https://github.com/quarkusio/quarkus-quickstarts.git
, or you can download an archive.
The solution is located in the security-openid-connect-quickstart
directory.
Maven プロジェクトの作成
You can either create a new Maven project with the oidc
extension or you can add the extension to an existing Maven project.
Complete one of the following commands:
To create a new Maven project, use the following command:
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'
これにより、 pom.xml
に以下が追加されます:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
implementation("io.quarkus:quarkus-oidc")
アプリケーションの記述
-
Implement the
/api/users/me
endpoint as shown in the following example, which is a regular Jakarta REST resource: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/admin
endpoint as shown in the following 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"; } }
The main difference in this example is that the
@RolesAllowed
annotation is used to verify that only users granted theadmin
role can access the endpoint.
SecurityIdentity
のインジェクションは、 @RequestScoped
と @ApplicationScoped
の両方のコンテキストでサポートされています。
アプリケーションの設定
-
Configure the Quarkus OpenID Connect (OIDC) extension by setting the following configuration properties in the
src/main/resources/application.properties
file.%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
sets the base URL of the OpenID Connect (OIDC) server. The%prod.
profile prefix ensures thatDev Services for Keycloak
launches a container when you run the application in development (dev) mode. For more information, see the アプリケーションを開発モードで実行する section. -
quarkus.oidc.client-id
sets a client id that identifies the application. -
quarkus.oidc.credentials.secret
sets the client secret, which is used by theclient_secret_basic
authentication method.
For more information, see the Quarkus OpenID Connect (OIDC) configuration properties guide.
Keycloakサーバーの起動と設定
-
Put the realm configuration file on the classpath (
target/classes
directory) so that it gets imported automatically when running in dev mode. You do not need to do this if you have already built a complete solution, in which case, this realm file is added to the classpath during the build.Do not start the Keycloak server when you run the application in dev mode;
Dev Services for Keycloak
will start a container. For more information, see the アプリケーションを開発モードで実行する section. -
To start a Keycloak server, you can use Docker to run the following command:
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.version
is set to version25.0.6
or later.
-
-
You can access your Keycloak server at localhost:8180.
-
To access the Keycloak Administration console, log in as the
admin
user by using the following login credentials:-
Username:
admin
-
Password:
admin
-
-
Import the realm configuration file from the upstream community repository to create a new realm.
For more information, see the Keycloak documentation about creating and configuring 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 |
アプリケーションを開発モードで実行する
-
To run the application in dev mode, run the following commands:
コマンドラインインタフェースquarkus dev
Maven./mvnw quarkus:dev
Gradle./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-ui. Then, in an
OpenID Connect
card, click theKeycloak provider
link . -
When prompted to log in to a
Single Page Application
provided byOpenID Connect Dev UI
, do the following steps:-
Log in as
alice
(password:alice
), who has auser
role.-
Accessing
/api/admin
returns a403
status code. -
Accessing
/api/users/me
returns a200
status code.
-
-
Log out and log in again as
admin
(password:admin
), who has bothadmin
anduser
roles.-
Accessing
/api/admin
returns a200
status code. -
Accessing
/api/users/me
returns a200
status code.
-
-
JVMモードでアプリケーションを実行
When you are done with dev mode, you can run the application as a standard Java application.
-
アプリケーションをコンパイルします:
コマンドラインインタフェースquarkus build
Maven./mvnw install
Gradle./gradlew build
-
アプリケーションの実行:
java -jar target/quarkus-app/quarkus-run.jar
ネイティブ・モードでアプリケーションを実行
You can compile this same demo as-is into native mode without 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
プロファイルを有効にして、アプリケーションを再度ビルドします。コマンドラインインタフェースquarkus build --native
Maven./mvnw install -Dnative
Gradle./gradlew build -Dquarkus.native.enabled=true
-
After waiting a little while, you run the following binary directly:
./target/security-openid-connect-quickstart-1.0.0-SNAPSHOT-runner
アプリケーションのテスト
For information about testing your application in dev mode, see the preceding アプリケーションを開発モードで実行する section.
You can test the application launched in JVM or native modes with curl
.
-
Because the application uses Bearer token authentication, you must first 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' \
)
When the
|
The preceding example obtains an access token for the user alice
.
-
Any user can access the
http://localhost:8080/api/users/me
endpoint, which returns a JSON payload with details about the user.
curl -v -X GET \
http://localhost:8080/api/users/me \
-H "Authorization: Bearer "$access_token
-
Only users with the
admin
role can access thehttp://localhost:8080/api/admin
endpoint. If you try to access this endpoint with the previously-issued access token, you get a403
response from the server.
curl -v -X GET \
http://localhost:8080/api/admin \
-H "Authorization: Bearer "$access_token
-
To access the admin endpoint, obtain a token for the
admin
user:
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.