The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

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.8

  • 動作するコンテナランタイム(Docker, Podman)

  • 使用したい場合は、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

  • jq コマンドラインプロセッサーツール

アーキテクチャ

この例では、2 つのエンドポイントを提供するシンプルなマイクロサービスをビルドする方法を示します。

  • /api/users/me

  • /api/admin

これらのエンドポイントは保護されており、クライアントがリクエストとともにベアラートークンを送信した場合にのみアクセスできます。ベアラートークンは有効 (署名、有効期限、audience など) であり、マイクロサービスによって信頼されている必要があります。

Keycloak サーバーはベアラートークンを発行し、トークンが発行されたサブジェクトを表します。 これは OAuth 2.0 認可サーバーであるため、トークンはユーザーに代わって動作するクライアントも参照します。

有効なトークンを持つすべてのユーザーは、/api/users/me エンドポイントにアクセスできます。 レスポンスとして、トークンの情報から取得したユーザーの詳細を含む JSON ドキュメントを返します。

/api/admin エンドポイントは RBAC (ロールベースのアクセス制御) で保護されており、admin ロールを持つユーザーのみがアクセスできます。 このエンドポイントでは、@RolesAllowed アノテーションを使用して、アクセス制約を宣言的に適用します。

ソリューション

次のセクションの指示に従って、アプリケーションを段階的に作成します。 完成した例に直接進むこともできます。

git clone -b 3.15 https://github.com/quarkusio/quarkus-quickstarts.git コマンドを実行して Git リポジトリーをクローンできます。または、https://github.com/quarkusio/quarkus-quickstarts/archive/3.15.zip[アーカイブ] をダウンロードできます。

ソリューションは、security-openid-connect-quickstart ディレクトリー にあります。

Maven プロジェクトの作成

oidc エクステンションを使用して新しい Maven プロジェクトを作成することも、既存の Maven プロジェクトにエクステンションを追加することもできます。 次のいずれかのコマンドを実行します。

新しい Maven プロジェクトを作成するには、次のコマンドを使用します。

コマンドラインインタフェース
quarkus create app org.acme:security-openid-connect-quickstart \
    --extension='oidc,rest-jackson' \
    --no-code
cd security-openid-connect-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストールと使用方法の詳細については、 Quarkus CLI ガイドを参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.15.7:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=security-openid-connect-quickstart \
    -Dextensions='oidc,rest-jackson' \
    -DnoCode
cd security-openid-connect-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=security-openid-connect-quickstart"

すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリーで以下のコマンドを実行することで、プロジェクトに oidc エクステンションを追加することができます。

コマンドラインインタフェース
quarkus extension add oidc
Maven
./mvnw quarkus:add-extension -Dextensions='oidc'
Gradle
./gradlew addExtension --extensions='oidc'

これにより、 pom.xml に以下が追加されます:

pom.xml
<dependency>
   <groupId>io.quarkus</groupId>
   <artifactId>quarkus-oidc</artifactId>
</dependency>
build.gradle
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;
            }
        }
    }
  2. 次の例に示すように、/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サーバーの起動と設定

  1. レルム設定ファイル をクラスパス (target/classes ディレクトリー) に配置し、開発モードで実行する際に自動的にインポートされるようにします。 すでに 完全なソリューション をビルド済みの場合は、このレルムファイルはビルド時にクラスパスに追加されるため、この手順は必要ありません。

    アプリケーションを開発モードで実行するときは、Keycloak サーバーを起動しないでください。Dev Services for Keycloak がコンテナーを起動します。 詳細は、アプリケーションを開発モードで実行する セクションを参照してください。

  2. 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.version is set to version 25.0.6 or later.

  3. Keycloak サーバーには localhost:8180 からアクセスできます。

  4. Keycloak 管理コンソールにアクセスするには、次のログイン認証情報を使用して admin ユーザーとしてログインします。

    • ユーザー名: admin

    • パスワード: admin

  5. 新しいレルムを作成するには、アップストリームコミュニティーリポジトリーから レルム設定ファイル をインポートします。

詳細は、Keycloak ドキュメントの 新しいレルムの作成と設定 を参照してください。

If you want to use the Keycloak Admin Client to configure your server from your application, you need to include either the quarkus-keycloak-admin-rest-client or the quarkus-keycloak-admin-resteasy-client (if the application uses quarkus-rest-client) extension. For more information, see the Quarkus Keycloak Admin Client guide.

アプリケーションを開発モードで実行する

  1. 開発モードでアプリケーションを実行するには、次のコマンドを実行します。

    コマンドラインインタフェース
    quarkus dev
    Maven
    ./mvnw quarkus:dev
    Gradle
    ./gradlew --console=plain quarkusDev
  2. /q/dev-ui にある Dev UI を開きます。 次に、OpenID Connect カードで、 Keycloak provider リンクをクリックします。

  3. OpenID Connect Dev UI によって提供される Single Page Application にログインするように求められたら、次の手順を実行します。

    • user ロールを持つ alice (パスワード: alice) としてログインします。

      • /api/admin にアクセスすると、ステータスコード 403 が返されます。

      • /api/users/me にアクセスすると、ステータスコード 200 が返されます。

    • ログアウトし、adminuser の両方のロールを持つ admin (パスワード: admin) として再度ログインします。

      • /api/admin にアクセスすると、ステータスコード 200 が返されます。

      • /api/users/me にアクセスすると、ステータスコード 200 が返されます。

JVMモードでアプリケーションを実行

開発モードが完了したら、アプリケーションを標準の Java アプリケーションとして実行できます。

  1. アプリケーションをコンパイルします:

    コマンドラインインタフェース
    quarkus build
    Maven
    ./mvnw install
    Gradle
    ./gradlew build
  2. アプリケーションの実行:

    java -jar target/quarkus-app/quarkus-run.jar

ネイティブ・モードでアプリケーションを実行

この同じデモを、変更を加えずにそのままネイティブモードにコンパイルできます。 これは、実稼働環境に JVM をインストールする必要がなくなることを意味します。 ランタイムテクノロジーは生成されたバイナリーに組み込まれ、必要最小限のリソースで実行できるように最適化されています。

コンパイルには少し時間がかかるため、この手順はデフォルトで無効になっています。

  1. native プロファイルを有効にして、アプリケーションを再度ビルドします。

    コマンドラインインタフェース
    quarkus build --native
    Maven
    ./mvnw install -Dnative
    Gradle
    ./gradlew build -Dquarkus.native.enabled=true
  2. しばらく待ってから、次のバイナリーを直接実行します。

    ./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 セクションを参照してください。

関連コンテンツ