The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
このページを編集

JWT RBAC の使用

このガイドでは、SmallRye JWT を Quarkus アプリケーションに統合し、MicroProfile JWT 仕様に準拠した JSON Web Token (JWT) セキュリティーを実装する方法を説明します。JWT の検証方法、MicroProfile JWT の org.eclipse.microprofile.jwt.JsonWebToken としての表現、およびベアラー認証と ロールベースアクセス制御 を使用して Quarkus の HTTP エンドポイントを保護する方法を学びます。

Quarkus の OpenID Connect (quarkus-oidc) エクステンションもベアラートークン認可をサポートしており、 smallrye-jwt を使用してベアラートークンを JsonWebToken として表現します。詳細については、OIDC ベアラートークン認証 ガイドを参照してください。

Quarkus アプリケーションで OIDC 認可コードフローを使用してユーザーを認証する必要がある場合は、OpenID Connect エクステンションを使用する必要があります。詳細については、Web アプリケーションを保護するための OIDC コードフローメカニズム を参照してください。

前提条件

このガイドを完成させるには、以下が必要です:

  • 約15分

  • IDE

  • JDK 17+がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.9.15

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

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

クイックスタート

ソリューション

アプリケーションを段階的に作成するには、次のセクションの指示に従うことを推奨します。必要に応じて、完成した例に進むこともできます。

例にアクセスするには、Git リポジトリーをクローンするか、アーカイブをダウンロードします。

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

Maven プロジェクトの作成

まず、以下のコマンドで新規プロジェクトを作成します。

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

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

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

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.35.2:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=security-jwt-quickstart \
    -Dextensions='rest-jackson,smallrye-jwt,smallrye-jwt-build' \
    -DnoCode
cd security-jwt-quickstart

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

Windowsユーザーの場合:

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

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

このコマンドは Maven プロジェクトを生成し、MicroProfile JWT RBAC サポートを含む smallrye-jwt エクステンションをインポートします。

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

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

このコマンドは、ビルドファイルに以下の依存関係を追加します。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-smallrye-jwt</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-smallrye-jwt-build</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-smallrye-jwt")
implementation("io.quarkus:quarkus-smallrye-jwt-build")

Jakarta REST リソースを調査する

REST エンドポイントを src/main/java/org/acme/security/jwt/TokenSecuredResource.java に以下の内容で作成します。

REST エンドポイント V1
package org.acme.security.jwt;

import jakarta.annotation.security.PermitAll;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.SecurityContext;

import org.eclipse.microprofile.jwt.JsonWebToken;

@Path("/secured")
public class TokenSecuredResource {

    @Inject
    JsonWebToken jwt; (1)

    @GET
    @Path("permit-all")
    @PermitAll (2)
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@Context SecurityContext ctx) {
        return getResponseString(ctx); (3)
    }

    private String getResponseString(SecurityContext ctx) {
        String name;
        if (ctx.getUserPrincipal() == null) { (4)
            name = "anonymous";
        } else if (!ctx.getUserPrincipal().getName().equals(jwt.getName())) { (5)
            throw new InternalServerErrorException("Principal and JsonWebToken names do not match");
        } else {
            name = ctx.getUserPrincipal().getName(); (6)
        }
        return String.format("hello %s,"
            + " isHttps: %s,"
            + " authScheme: %s,"
            + " hasJWT: %s",
            name, ctx.isSecure(), ctx.getAuthenticationScheme(), hasJwt()); (7)
    }

    private boolean hasJwt() {
        return jwt.getClaimNames() != null;
    }
}
1 JsonWebToken インターフェイスが挿入され、現在の認証済みトークンに関連付けられたクレームにアクセスできるようになります。このインターフェイスは java.security.Principal を継承します。
2 @PermitAll は標準の Jakarta セキュリティーアノテーションです。これは、認証されているかどうかに関係なく、指定されたエンドポイントがすべての呼び出し元からアクセスできることを示します。
3 Jakarta REST SecurityContext は、リクエストのセキュリティー状態を検査するために挿入されます。 getResponseString() 関数は応答を生成します。
4 リクエストのユーザー/呼び出し元の Principal を null と照合して、呼び出しが安全でないかどうかを確認します。
5 JsonWebToken は現在の Principal を表すため、 PrincipalJsonWebToken の名前が一致することを確認します。
6 Principal の名前を取得します。
7 呼び出し元の名前、リクエスト SecurityContextisSecure() および getAuthenticationScheme() の状態、そして null 以外の JsonWebToken が挿入されたかどうかを含む応答を構築します。

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

これで、次のいずれかのコマンドを使用して、アプリケーションを開発モードで実行する準備が整いました。

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

次に、以下の例のような出力が表示されるはずです。

quarkus:dev 出力
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.acme:security-jwt-quickstart >-----------------------
[INFO] Building security-jwt-quickstart 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
...
Listening for transport dt_socket at address: 5005
2020-07-15 16:09:50,883 INFO  [io.quarkus] (Quarkus Main Thread) security-jwt-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 999-SNAPSHOT) started in 1.073s. Listening on: http://0.0.0.0:8080
2020-07-15 16:09:50,885 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2020-07-15 16:09:50,885 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, mutiny, rest, rest-jackson, security, smallrye-context-propagation, smallrye-jwt, vertx, vertx-web]

REST エンドポイントが実行されているので、curl などのコマンドラインツールを使用してアクセスできます。

/secured/permit-all に対する curl コマンド
$ curl http://127.0.0.1:8080/secured/permit-all; echo

このコマンドは次の応答を返します。

hello anonymous, isHttps: false, authScheme: null, hasJWT: false

リクエストで JWT が提供されていないため、エンドポイントでセキュリティー状態が確認されることはなく、応答もそれと一致しています。

  • username は匿名です。

  • https が使用されていないため、 isHttpsfalse です。

  • authSchemenull です。

  • hasJWTfalse です。

Ctrl-C を使用して Quarkus サーバーを停止します。

では実際に何かをセキュア化してみましょう。下記の新しいエンドポイントメソッド helloRolesAllowed を見てみましょう。

REST エンドポイント V2
package org.acme.security.jwt;

import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.SecurityContext;

import org.eclipse.microprofile.jwt.JsonWebToken;

@Path("/secured")
public class TokenSecuredResource {

    @Inject
    JsonWebToken jwt; (1)

    @GET
    @Path("permit-all")
    @PermitAll
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@Context SecurityContext ctx) {
        return getResponseString(ctx);
    }

    @GET
    @Path("roles-allowed") (2)
    @RolesAllowed({ "User", "Admin" }) (3)
    @Produces(MediaType.TEXT_PLAIN)
    public String helloRolesAllowed(@Context SecurityContext ctx) {
        return getResponseString(ctx) + ", birthdate: " + jwt.getClaim("birthdate").toString(); (4)
    }

    private String getResponseString(SecurityContext ctx) {
        String name;
        if (ctx.getUserPrincipal() == null) {
            name = "anonymous";
        } else if (!ctx.getUserPrincipal().getName().equals(jwt.getName())) {
            throw new InternalServerErrorException("Principal and JsonWebToken names do not match");
        } else {
            name = ctx.getUserPrincipal().getName();
        }
        return String.format("hello %s,"
            + " isHttps: %s,"
            + " authScheme: %s,"
            + " hasJWT: %s",
            name, ctx.isSecure(), ctx.getAuthenticationScheme(), hasJwt());
    }

    private boolean hasJwt() {
        return jwt.getClaimNames() != null;
    }
}
1 JWT からのクレームにアクセスするために、 JsonWebToken が挿入されます。
2 このエンドポイントは /secured/roles-allowed で公開されます。
3 @RolesAllowed アノテーションは、"User" または "Admin" ロールを持つユーザーへのアクセスを制限します。
4 応答は hello メソッドと同様に構築されますが、挿入された JsonWebToken から直接取得された birthdate クレームが追加されます。

TokenSecuredResource にこれを追加した後、 ./mvnw quarkus:dev コマンドを再実行し、次に curl -v http://127.0.0.1:8080/secured/roles-allowed; echo を試して新しいエンドポイントへのアクセスを試みます。

出力は以下のようになるはずです。

/secured/roles-allowedcurl コマンド
$ curl -v http://127.0.0.1:8080/secured/roles-allowed; echo

このコマンドは次の応答を返します。

*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET /secured/roles-allowed HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Connection: keep-alive
< Content-Type: text/html;charset=UTF-8
< Content-Length: 14
< Date: Sun, 03 Mar 2019 16:32:34 GMT
<
* Connection #0 to host 127.0.0.1 left intact

素晴らしいです。 リクエストに JWT を含めなかったため、エンドポイントへのアクセスは正しく拒否されました。 代わりに、HTTP 401 Unauthorized エラーが返されました。

エンドポイントにアクセスするには、有効な JWT を取得してリクエストに含める必要があります。これには次の 2 つの手順が含まれます。

  1. JWT を検証するために必要な情報で SmallRye JWT エクステンションを設定します。

  2. 設定に一致する適切なクレームを含む JWT を生成します。

SmallRye JWT エクステンションのセキュリティー情報を設定する

次の内容で security-jwt-quickstart/src/main/resources/application.properties を作成します。

TokenSecuredResource のアプリケーションプロパティー
mp.jwt.verify.publickey.location=publicKey.pem (1)
mp.jwt.verify.issuer=https://example.com/issuer (2)

quarkus.native.resources.includes=publicKey.pem (3)
1 クラスパス上の公開鍵ファイル publicKey.pem の場所を指定します。 このキーの追加については、公開鍵の追加 を参照してください。
2 想定される発行者を https://example.com/issuer として定義します。
3 publicKey.pem ファイルがネイティブ実行可能ファイルのリソースとして含まれることを保証します。

公開鍵の追加

JWT 仕様 では、使用できる JWT のさまざまなセキュリティーレベルが定義されています。 MicroProfile JWT RBAC 仕様では、RSA-256 署名アルゴリズムで署名された JWT が必要です。 これには、RSA 公開鍵ペアが必要になります。 REST エンドポイントサーバー側では、リクエストとともに送信された JWT を検証するために使用する RSA 公開鍵の場所を設定する必要があります。 以前に設定された mp.jwt.verify.publickey.location=publicKey.pem 設定では、公開鍵がクラスパス上で publicKey.pem として使用可能であることが想定されています。 これを実現するには、次のコンテンツを security-jwt-quickstart/src/main/resources/publicKey.pem ファイルにコピーします。

RSA 公開鍵 PEM コンテンツ
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq
Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR
TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e
UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9
AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn
sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x
nQIDAQAB
-----END PUBLIC KEY-----

JWT の生成

多くの場合、JWT は Keycloak などのアイデンティティーマネージャーから取得されます。 ただし、このクイックスタートでは、 smallrye-jwt によって提供される JWT 生成 API を使用して独自の JWT を生成します。 詳細については、SmallRye JWT を使用して JWT トークンを生成する を参照してください。

次のリストからコードを取得し、 security-jwt-quickstart/src/test/java/org/acme/security/jwt/GenerateToken.java に配置します。

GenerateToken メインドライバークラス
package org.acme.security.jwt;

import java.util.Arrays;
import java.util.HashSet;

import org.eclipse.microprofile.jwt.Claims;
import io.smallrye.jwt.build.Jwt;

/**
 * A utility class to generate and print a JWT token string to stdout.
 */
public class GenerateToken {

    /**
     * Generates and prints a JWT token.
     */
    public static void main(String[] args) {
        String token = Jwt.issuer("https://example.com/issuer") (1)
                .upn("jdoe@quarkus.io") (2)
                .groups(new HashSet<>(Arrays.asList("User", "Admin"))) (3)
                .claim(Claims.birthdate.name(), "2001-07-13") (4)
                .sign();

        System.out.println(token);
        System.exit(0);
    }
}
1 JWT に iss (発行者) クレームを設定します。 トークンが有効と見なされるためには、この値がサーバー側の mp.jwt.verify.issuer 設定と一致する必要があります。
2 upn (ユーザープリンシパル名) クレームを指定します。これは MicroProfile JWT RBAC 仕様で、コンテナーセキュリティー API における Principal の識別に使用される推奨クレームとして定義されています。
3 JWT ベアラーに割り当てられたグループメンバーシップと最上位レベルのロールを提供する groups クレームを定義します。
4 birthdate クレームを追加します。 これは機密情報とみなされる可能性があるため、SmallRye JWT を使用して JWT トークンを生成する で説明されているようにクレームを暗号化することを検討してください。

このコードが機能するには、 TokenSecuredResource アプリケーションにある公開鍵に対応する RSA 秘密鍵の内容が必要であることに注意してください。 次の PEM コンテンツを取得して、 security-jwt-quickstart/src/test/resources/privateKey.pem に配置します。

RSA 秘密鍵 PEM コンテンツ
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCWK8UjyoHgPTLa
PLQJ8SoXLLjpHSjtLxMqmzHnFscqhTVVaDpCRCb6e3Ii/WniQTWw8RA7vf4djz4H
OzvlfBFNgvUGZHXDwnmGaNVaNzpHYFMEYBhE8VGGiveSkzqeLZI+Y02G6sQAfDtN
qqzM/l5QX8X34oQFaTBW1r49nftvCpITiwJvWyhkWtXP9RP8sXi1im5Vi3dhupOh
nelk5n0BfajUYIbfHA6ORzjHRbt7NtBl0L2J+0/FUdHyKs6KMlFGNw8O0Dq88qnM
uXoLJiewhg9332W3DFMeOveel+//cvDnRsCRtPgd4sXFPHh+UShkso7+DRsChXa6
oGGQD3GdAgMBAAECggEAAjfTSZwMHwvIXIDZB+yP+pemg4ryt84iMlbofclQV8hv
6TsI4UGwcbKxFOM5VSYxbNOisb80qasb929gixsyBjsQ8284bhPJR7r0q8h1C+jY
URA6S4pk8d/LmFakXwG9Tz6YPo3pJziuh48lzkFTk0xW2Dp4SLwtAptZY/+ZXyJ6
96QXDrZKSSM99Jh9s7a0ST66WoxSS0UC51ak+Keb0KJ1jz4bIJ2C3r4rYlSu4hHB
Y73GfkWORtQuyUDa9yDOem0/z0nr6pp+pBSXPLHADsqvZiIhxD/O0Xk5I6/zVHB3
zuoQqLERk0WvA8FXz2o8AYwcQRY2g30eX9kU4uDQAQKBgQDmf7KGImUGitsEPepF
KH5yLWYWqghHx6wfV+fdbBxoqn9WlwcQ7JbynIiVx8MX8/1lLCCe8v41ypu/eLtP
iY1ev2IKdrUStvYRSsFigRkuPHUo1ajsGHQd+ucTDf58mn7kRLW1JGMeGxo/t32B
m96Af6AiPWPEJuVfgGV0iwg+HQKBgQCmyPzL9M2rhYZn1AozRUguvlpmJHU2DpqS
34Q+7x2Ghf7MgBUhqE0t3FAOxEC7IYBwHmeYOvFR8ZkVRKNF4gbnF9RtLdz0DMEG
5qsMnvJUSQbNB1yVjUCnDAtElqiFRlQ/k0LgYkjKDY7LfciZl9uJRl0OSYeX/qG2
tRW09tOpgQKBgBSGkpM3RN/MRayfBtmZvYjVWh3yjkI2GbHA1jj1g6IebLB9SnfL
WbXJErCj1U+wvoPf5hfBc7m+jRgD3Eo86YXibQyZfY5pFIh9q7Ll5CQl5hj4zc4Y
b16sFR+xQ1Q9Pcd+BuBWmSz5JOE/qcF869dthgkGhnfVLt/OQzqZluZRAoGAXQ09
nT0TkmKIvlza5Af/YbTqEpq8mlBDhTYXPlWCD4+qvMWpBII1rSSBtftgcgca9XLB
MXmRMbqtQeRtg4u7dishZVh1MeP7vbHsNLppUQT9Ol6lFPsd2xUpJDc6BkFat62d
Xjr3iWNPC9E9nhPPdCNBv7reX7q81obpeXFMXgECgYEAmk2Qlus3OV0tfoNRqNpe
Mb0teduf2+h3xaI1XDIzPVtZF35ELY/RkAHlmWRT4PCdR0zXDidE67L6XdJyecSt
FdOUH8z5qUraVVebRFvJqf/oGsXc4+ex1ZKUTbY0wqY1y9E39yvB3MaTmZFuuqk8
f3cg+fr8aou7pr9SHhJlZCU=
-----END PRIVATE KEY-----

後で、 smallrye.jwt.sign.key.location プロパティーを設定して、秘密署名鍵の場所を指定します。

OpenSSL を使用した鍵の生成

OpenSSL コマンドラインツールを使用して公開鍵と秘密鍵のペアを生成することも可能です。

鍵を生成するための openssl コマンド
openssl genrsa -out rsaPrivateKey.pem 2048
openssl rsa -pubout -in rsaPrivateKey.pem -out publicKey.pem

秘密鍵を生成し、安全なキーの保管と転送に一般的に使用される PKCS#8 形式に変換するには、追加の手順が必要です。

変換を実行するための openssl コマンド
openssl pkcs8 -topk8 -nocrypt -inform pem -in rsaPrivateKey.pem -outform pem -out privateKey.pem

このクイックスタートで使用されているキーペアの代わりに、生成されたキーペアを使用できます。

TokenSecuredResource エンドポイントの JSON Web Token (JWT) を生成する前に、アプリケーションが実行されていること を確認してください。

次に、次のコマンドを使用して JWT を生成します。

JWT 生成出力のサンプル
$ mvn exec:java -Dexec.mainClass=org.acme.security.jwt.GenerateToken -Dexec.classpathScope=test -Dsmallrye.jwt.sign.key.location=privateKey.pem

JWT 文字列は、 . 文字で区切られた 3 つの部分で構成される Base64 URL エンコードされた文字列です。

  1. 署名アルゴリズムなど、トークンに関するメタデータを含むヘッダー。

  2. ペイロード (「クレーム」とも呼ばれます) には、トークンのクレームまたはデータが含まれます。

  3. トークンの整合性を検証する署名。

最後に、/secured/roles-allowed へのセキュリティーで保護されたアクセス

ここで、これを使用して、 /secured/roles-allowed エンドポイントにセキュリティー保護されたリクエストを送信してみましょう。 Quarkus サーバーが開発モードでまだ実行されていることを確認してから、次のコマンドを実行し、前の手順で生成された JWT のバージョンを必ず使用してください。

JWT を含む /secured/roles-allowedcurl コマンド
$ curl -H "Authorization: Bearer eyJraWQ..." http://127.0.0.1:8080/secured/roles-allowed; echo

生成されたトークンを HTTP 認可 Bearer スキームの値として必ず使用してください。

このコマンドは次の応答を返します。

hello jdoe@quarkus.io, isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13

正常に完了しました。これで次のようになりました。

  • 匿名でない呼び出し元の名前: jdoe@quarkus.io

  • 認証スキーム: Bearer

  • null 以外の JsonWebToken

  • birthdate クレーム値

JsonWebToken とクレームインジェクションの使用

これで、セキュリティー保護された REST エンドポイントにアクセスするための JWT を生成できるようになりました。次に、 JsonWebToken インターフェイスと JWT クレームを使用して何ができるかを見てみましょう。 org.eclipse.microprofile.jwt.JsonWebToken インターフェイスは java.security.Principal インターフェイスを継承し、以前に使用した jakarta.ws.rs.core.SecurityContext#getUserPrincipal() 呼び出しによって返されるオブジェクトタイプです。 つまり、CDI を使用しくても REST コンテナー SecurityContext にアクセスできるコードは、 SecurityContext#getUserPrincipal() をキャストすることで、呼び出し元の JsonWebToken インターフェイスを取得できます。

JsonWebToken インターフェイスは、基盤となる JWT のクレームにアクセスするためのメソッドを定義します。これは、MicroProfile JWT RBAC 仕様で必須とされる共通のクレーム、および JWT に存在する可能性のある任意のクレームのアクセッサを提供します。

すべての JWT クレームを注入することもできます。 (JsonWebToken から取得するのではなく) 注入された birthdate クレームを使用する別のエンドポイント /secured/roles-allowed-adminTokenSecuredResource を拡張してみましょう。

package org.acme.security.jwt;

import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.SecurityContext;

import org.eclipse.microprofile.jwt.Claim;
import org.eclipse.microprofile.jwt.Claims;
import org.eclipse.microprofile.jwt.JsonWebToken;

@Path("/secured")
@RequestScoped (1)
public class TokenSecuredResource {

    @Inject
    JsonWebToken jwt; (2)
    @Inject
    @Claim(standard = Claims.birthdate)
    String birthdate; (3)

    @GET
    @Path("permit-all")
    @PermitAll
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@Context SecurityContext ctx) {
        return getResponseString(ctx);
    }

    @GET
    @Path("roles-allowed")
    @RolesAllowed({ "User", "Admin" })
    @Produces(MediaType.TEXT_PLAIN)
    public String helloRolesAllowed(@Context SecurityContext ctx) {
        return getResponseString(ctx) + ", birthdate: " + jwt.getClaim("birthdate").toString();
    }

    @GET
    @Path("roles-allowed-admin")
    @RolesAllowed("Admin")
    @Produces(MediaType.TEXT_PLAIN)
    public String helloRolesAllowedAdmin(@Context SecurityContext ctx) {
        return getResponseString(ctx) + ", birthdate: " + birthdate; (4)
    }

    private String getResponseString(SecurityContext ctx) {
        String name;
        if (ctx.getUserPrincipal() == null) {
            name = "anonymous";
        } else if (!ctx.getUserPrincipal().getName().equals(jwt.getName())) {
            throw new InternalServerErrorException("Principal and JsonWebToken names do not match");
        } else {
            name = ctx.getUserPrincipal().getName();
        }
        return String.format("hello %s,"
            + " isHttps: %s,"
            + " authScheme: %s,"
            + " hasJWT: %s",
            name, ctx.isSecure(), ctx.getAuthenticationScheme(), hasJwt());
    }

    private boolean hasJwt() {
        return jwt.getClaimNames() != null;
    }
}
1 birthdate クレームを String として注入できるようにするには、 @RequestScoped スコープが必要です。
2 ここで JsonWebToken が注入され、すべてのクレームおよび JWT 関連情報へのアクセスが提供されます。
3 birthdate クレームは String として注入されます。これが、 @RequestScoped スコープが必須である理由を示しています。
4 注入された birthdate クレームは、応答を構築するために直接使用されます。

次に、トークンを再度生成して実行します。

$ curl -H "Authorization: Bearer eyJraWQ..." http://127.0.0.1:8080/secured/roles-allowed-admin; echo

生成されたトークンを HTTP 認可 Bearer スキームの値として必ず使用してください。

このコマンドは次の応答を返します。

hello jdoe@quarkus.io, isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13

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

アプリケーションを標準の Java アプリケーションとして実行できます。

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

    CLI
    quarkus build
    Maven
    ./mvnw install
    Gradle
    ./gradlew build
  2. アプリケーションを実行します。

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

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

この同じデモを、変更なしでネイティブモードにコンパイルできます。 これにより、本番環境に JVM をインストールする必要がなくなります。 ランタイム技術は生成されたバイナリーに含まれ、最小限のリソースで実行できるよう最適化されています。

コンパイルには時間がかかるため、このステップはデフォルトで無効になっています。

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

    CLI
    quarkus build --native
    Maven
    ./mvnw install -Dnative
    Gradle
    ./gradlew build -Dquarkus.native.enabled=true
  2. 次のバイナリーを直接実行します。

    ./target/security-jwt-quickstart-1.0.0-SNAPSHOT-runner

ソリューションを探索する

security-jwt-quickstart directory リポジトリーには、このクイックスタートガイドで取り上げるすべてのバージョンと、CDI API を介して注入された JsonWebToken トークンおよびそのクレームを使用するサブリソースを示す追加のエンドポイントが含まれています。

security-jwt-quickstart ディレクトリーを探索し、クイックスタートソリューションを確認して、SmallRye JWT エクステンションの機能についてさらに学ぶことをお勧めします。

リファレンスガイド

サポートされている注入スコープ

org.eclipse.microprofile.jwt.JsonWebToken が注入される場合、 @ApplicationScoped@Singleton、および @RequestScoped の外部 Bean 注入スコープはすべてサポートされます。現在のトークンが表されるように、 JsonWebToken には @RequestScoped スコープが強制されます。

ただし、個々のトークンクレームが String のような単純な型として注入される場合、 @RequestScoped を使用する必要があります。例:

package org.acme.security.jwt;

import jakarta.inject.Inject;
import org.eclipse.microprofile.jwt.Claim;
import org.eclipse.microprofile.jwt.Claims;

@Path("/secured")
@RequestScoped
public class TokenSecuredResource {

    @Inject
    @Claim(standard = Claims.birthdate)
    String birthdate;
}

注入された JsonWebToken を使用して個々のクレームにアクセスすることもできますが、この場合は @RequestScoped を設定する必要はありません。

詳細については、 MP JWT CDI Injection Requirements を参照してください。

サポートされている公開鍵形式

公開鍵は、以下のいずれかの形式でフォーマットできます。優先順位順に示します。

  • Public Key Cryptography Standards #8 (PKCS#8) PEM

  • JSON Web Key (JWK)

  • JSON Web Key Set (JWKS)

  • JSON Web Key (JWK) Base64 URL エンコード

  • JSON Web Key Set (JWKS) Base64 URL エンコード

検証鍵の扱い

非対称 RSA または楕円曲線 (EC) 鍵を使用してトークン署名を検証する必要がある場合は、 mp.jwt.verify.publickey.location プロパティーを使用してローカルまたはリモートの検証鍵を参照します。

mp.jwt.verify.publickey.algorithm を使用して検証アルゴリズムをカスタマイズします (デフォルトは RS256)。たとえば、EC 鍵を使用する場合は ES256 に設定します。

対称秘密鍵を使用してトークン署名を検証する必要がある場合は、この秘密鍵を表すために JSON Web Key (JWK) または JSON Web Key Set (JWK Set) 形式のいずれかを使用する必要があります。例:

{
 "keys": [
   {
     "kty":"oct",
     "kid":"secretKey",
     "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"
   }
 ]
}

この秘密鍵 JWK は、 smallrye.jwt.verify.key.location でも参照する必要があります。 smallrye.jwt.verify.algorithmHS256/HS384/HS512 に設定する必要があります。

JWTParser を使用して JsonWebToken を解析および検証する

JWT トークンを注入できない場合、たとえば、サービスリクエストペイロードに埋め込まれている場合や、サービスエンドポイントが帯域外で取得する場合、 JWTParser を使用できます。

import org.eclipse.microprofile.jwt.JsonWebToken;
import io.smallrye.jwt.auth.principal.JWTParser;
...
@Inject JWTParser parser;

String token = getTokenFromOidcServer();

// Parse and verify the token
JsonWebToken jwt = parser.parse(token);

トークンがどのように検証または復号化されるかをカスタマイズするためにも使用できます。 たとえば、ローカルの SecretKey を提供できます。

package org.acme.security.jwt;

import io.smallrye.jwt.auth.principal.ParseException;
import jakarta.inject.Inject;
import jakarta.ws.rs.CookieParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.jwt.JsonWebToken;
import io.smallrye.jwt.auth.principal.JWTParser;
import io.smallrye.jwt.build.Jwt;

@Path("/secured")
public class SecuredResource {
    private static final String SECRET = "AyM1SysPpbyDfgZld3umj1qzKObwVMko";

    @Inject
    JWTParser parser;

    @GET
    @Produces("text/plain")
    public Response getUserName(@CookieParam("jwt") String jwtCookie) throws ParseException {
        if (jwtCookie == null) {
            // Create a JWT token signed by using the 'HS256' algorithm
            String newJwtCookie = Jwt.upn("Alice").signWithSecret(SECRET);
            // or create a JWT token encrypted by using the 'A256KW' algorithm
            // Jwt.upn("alice").encryptWithSecret(secret);
            return Response.ok("Alice").cookie(new NewCookie("jwt", newJwtCookie)).build();
        } else {
            // All mp.jwt and smallrye.jwt properties are still effective; only the verification key is customized.
            JsonWebToken jwt = parser.verify(jwtCookie, SECRET);
            // or jwt = parser.decrypt(jwtCookie, secret);
            return Response.ok(jwt.getName()).build();
        }
    }
}

quarkus-smallrye-jwt が提供する HTTP サポートなしで JWTParser を使用する方法については、 How to Add SmallRye JWT directly セクションも参照してください。

トークンの復号化

アプリケーションが暗号化されたクレームまたは暗号化された内部署名付きクレームを持つトークンを受け入れる必要がある場合は、 smallrye.jwt.decrypt.key.location プロパティーを復号化キーを指すように設定するだけです。

これが唯一設定されているキープロパティーである場合、受信トークンには暗号化されたクレームのみが含まれると予想されます。 mp.jwt.verify.publickey または mp.jwt.verify.publickey.location の検証プロパティーも設定されている場合、受信トークンには暗号化された内部署名付きトークンが含まれると予想されます。

SmallRye JWT を使用した JWT トークンの生成 を参照し、暗号化または内部署名された後に暗号化されたトークンを素早く生成する方法を学びましょう。

カスタムファクトリー

io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipalFactory は、JWT トークンを解析および検証し、それらを JsonWebToken プリンシパルに変換するために使用されるデフォルトの実装です。このファクトリーは、Configuration セクションで説明されているように、MP JWT および smallrye-jwt プロパティーに依存して JWT トークンを検証およびカスタマイズします。

すでにファイアウォールによって検証されたトークンの再検証をスキップするなど、カスタムファクトリーを実装する必要がある場合は、次のいずれかの方法で行うことができます。

  • META-INF/services/io.smallrye.jwt.auth.principal.JWTCallerPrincipalFactory リソースを作成して、 ServiceLoader メカニズムを使用します。

  • 以下の例のように、 Alternative CDI Bean 実装を提供します。

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import jakarta.annotation.Priority;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Alternative;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipal;
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
import io.smallrye.jwt.auth.principal.JWTCallerPrincipal;
import io.smallrye.jwt.auth.principal.JWTCallerPrincipalFactory;
import io.smallrye.jwt.auth.principal.ParseException;

@ApplicationScoped
@Alternative
@Priority(1)
public class TestJWTCallerPrincipalFactory extends JWTCallerPrincipalFactory {

    @Override
    public JWTCallerPrincipal parse(String token, JWTAuthContextInfo authContextInfo) throws ParseException {
        try {
            // Token has already been verified; parse the token claims only
            String json = new String(Base64.getUrlDecoder().decode(token.split("\\.")[1]), StandardCharsets.UTF_8);
            return new DefaultJWTCallerPrincipal(JwtClaims.parse(json));
        } catch (InvalidJwtException ex) {
            throw new ParseException(ex.getMessage());
        }
    }
}

ブロッキング呼び出し

quarkus-smallrye-jwt エクステンションでは、現在リアクティブではない SmallRye JWT ライブラリを使用します。

quarkus-smallrye-jwt がリアクティブな Quarkus セキュリティーアーキテクチャーの一部として動作する観点からすると、SmallRye JWT 検証または復号化コードに入る IO スレッドが、以下のいずれかのケースでブロックされる可能性があります。

  • デフォルトのキーリゾルバーは、キーを含む JsonWebKey セットを更新します。これには OIDC エンドポイントへのリモート呼び出しが含まれます。

  • AWS Application Load Balancer (ALB) キーリゾルバーなどのカスタムキーリゾルバーは、現在のトークンのキー識別子ヘッダー値を使用して、AWS ALB キーエンドポイントに対してキーを解決します。

このような場合、接続が遅い場合 (たとえば、キーエンドポイントへの応答に 3 秒以上かかる場合)、現在のイベントループスレッドがブロックされる可能性があります。

ブロックされないようにするには、 quarkus.smallrye-jwt.blocking-authentication=true を設定します。

トークンの伝播

下流サービスへのベアラーアクセストークンの伝播については、トークン伝播 の項を参照してください。

テスト

自動鍵生成

このエクステンションは、検証キーが設定されていない場合、開発モードとテストモードで非対称 RSA 2024 ビット署名キーペアを生成します。キーペアが生成されると、公開 RSA キーは mp.jwt.verify.publickey プロパティーを設定するために使用され、RSA 秘密キーは smallrye-jwt-build を使用してトークンに署名するためにテストで利用可能になります。例えば次のとおりです。

import io.smallrye.jwt.build.Jwt;
import jakarta.ws.rs.GET;

@GET
public String token() {
   return Jwt.upn("Alice").sign();
}

詳細については、クレーム署名ガイド を参照してください。

以下のプロパティーの少なくとも 1 つを設定することで、自動キー生成を無効にできます。

  • mp.jwt.verify.publickey.location

  • mp.jwt.verify.publickey

  • mp.jwt.decrypt.key.location

  • smallrye.jwt.encrypt.key.location

  • smallrye.jwt.sign.key.location

  • smallrye.jwt.sign.key

開発モード では、mp.jwt.verify.issuer プロパティーを使用して発行者を明示的に設定しない場合、SmallRye JWT エクステンションは、デフォルトの発行者として https://quarkus.io/issuer を設定します。

発行者をプログラムで設定したい場合は、デフォルト値が適用されないように mp.jwt.verify.issuerNONE に設定します。

Wiremock

mp.jwt.verify.publickey.location を HTTPS または HTTP ベースの JsonWebKey (JWK) セットを指すように設定する場合は、OpenID Connect Bearer Token Integration testingWiremock セクションで説明されているのと同じアプローチを使用できますが、 application.properties を変更して MP JWT 設定プロパティーを使用するだけです。

# keycloak.url is set by OidcWiremockTestResource
mp.jwt.verify.publickey.location=${keycloak.url}/realms/quarkus/protocol/openid-connect/certs
mp.jwt.verify.issuer=${keycloak.url}/realms/quarkus

Keycloak

Keycloak を使用していて、 mp.jwt.verify.publickey.location を HTTPS または HTTP ベースの JsonWebKey (JWK) セットを指すように設定する場合は、OpenID Connect Bearer Token Integration testing の Keycloak セクションで説明されているのと同じアプローチを使用できますが、 application.properties を変更して MP JWT 設定プロパティーを使用するだけです。

# keycloak.url is set by DevServices for Keycloak
mp.jwt.verify.publickey.location=${keycloak.url}/realms/quarkus/protocol/openid-connect/certs
mp.jwt.verify.issuer=${keycloak.url}/realms/quarkus

Keycloak が発行するトークンには、レルムエンドポイントアドレスが iss (発行者) クレームに設定されていることに注意してください。

Quarkus アプリケーションが Docker コンテナー内で実行される場合、DevServices for Keycloak によって起動された Keycloak コンテナーとネットワークインターフェイスを共有する可能性があります。このシナリオでは、Quarkus アプリケーションと Keycloak は内部の共有 Docker ネットワークを介して通信します。

そのような場合は、代わりに以下の設定を使用します。

# keycloak.url is set by DevServices for Keycloak,
# Quarkus accesses it through an internal shared docker network interface.
mp.jwt.verify.publickey.location=${keycloak.url}/realms/quarkus/protocol/openid-connect/certs

# Issuer is set to the docker bridge localhost endpoint address represented by the `client.quarkus.oidc.auth-server-url` property
mp.jwt.verify.issuer=${client.quarkus.oidc.auth-server-url}

ローカル公開鍵

OpenID Connect Bearer Token Integration testingLocal public key セクションで説明されているのと同じアプローチを使用できますが、 application.properties を変更して MP JWT 設定プロパティーを使用するだけです。

mp.jwt.verify.publickey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEqFyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwRTYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5eUF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYnsIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9xnQIDAQAB
# set it to the issuer value which is used to generate the tokens
mp.jwt.verify.issuer=${keycloak.url}/realms/quarkus

# required to sign the tokens
smallrye.jwt.sign.key.location=privateKey.pem

TestSecurity アノテーション

次の依存関係を追加します。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-test-security-jwt</artifactId>
    <scope>test</scope>
</dependency>
build.gradle
testImplementation("io.quarkus:quarkus-test-security-jwt")

次に、以下のようなテストコードを記述します。

import static org.hamcrest.Matchers.is;
import org.junit.jupiter.api.Test;
import io.quarkus.test.common.http.TestHTTPEndpoint;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import io.quarkus.test.security.jwt.Claim;
import io.quarkus.test.security.jwt.JwtSecurity;
import io.restassured.RestAssured;

@QuarkusTest
@TestHTTPEndpoint(ProtectedResource.class)
public class TestSecurityAuthTest {

    @Test
    @TestSecurity(user = "userJwt", roles = "viewer")
    public void testJwt() {
        RestAssured.when().get("test-security-jwt").then()
                .body(is("userJwt:viewer"));
    }

    @Test
    @TestSecurity(user = "userJwt", roles = "viewer")
    @JwtSecurity(claims = {
            @Claim(key = "email", value = "user@gmail.com")
    })
    public void testJwtWithClaims() {
        RestAssured.when().get("test-security-jwt-claims").then()
                .body(is("userJwt:viewer:user@gmail.com"));
    }

}

ここで、 ProtectedResource クラスは次のようになります。

@Path("/web-app")
@Authenticated
public class ProtectedResource {

    @Inject
    JsonWebToken accessToken;

    @GET
    @Path("test-security-jwt")
    public String testSecurityOidc() {
        return accessToken.getName() + ":" + accessToken.getGroups().iterator().next();
    }

    @GET
    @Path("test-security-jwt-claims")
    public String testSecurityOidcUserInfoMetadata() {
        return accessToken.getName() + ":" + accessToken.getGroups().iterator().next()
                + ":" + accessToken.getClaim("email");
    }
}

@TestSecurity アノテーションは常に使用する必要があり、その user プロパティーは JsonWebToken.getName() として返され、 roles プロパティーは JsonWebToken.getGroups() として返されることに注意してください。 @JwtSecurity アノテーションはオプションであり、追加のトークンクレームを設定するために使用できます。

@TestSecurity@JwtSecurity は、次のようにメタアノテーションで組み合わせることができます。

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD })
    @TestSecurity(user = "userOidc", roles = "viewer")
    @OidcSecurity(introspectionRequired = true,
        introspection = {
            @TokenIntrospection(key = "email", value = "user@gmail.com")
        }
    )
    public @interface TestSecurityMetaAnnotation {

    }

これは、同じセキュリティー設定のセットを複数のテストメソッドで使用する必要がある場合に特に便利です。

ログでエラーを確認する方法

トークンの検証または復号化エラーの詳細を確認するには、 io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator TRACE レベルのログを有効にしてください。

quarkus.log.category."io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator".level=TRACE
quarkus.log.category."io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator".min-level=TRACE

プロアクティブ認証

パブリックエンドポイントメソッド呼び出し時のトークン検証を省略したい場合は、 プロアクティブ認証 を無効にします。

トークンの検証が行われていない場合、挿入された JsonWebToken にパブリックメソッドを通じてアクセスできないことに注意してください。

SmallRye JWT を直接追加する方法

JWTParser を使用して JsonWebToken を解析および検証する には、以下の状況では quarkus-smallrye-jwt の代わりに smallrye-jwt を直接使用してください。

  • Quarkus GRPC のように、 HTTP をサポートしない Quarkus エクステンションを使用している場合。

  • Quarkus AWS Lambda のように、 quarkus-smallrye-jwtVert.x HTTP が提供するサポートと競合する、エクステンション固有の HTTP サポートを提供している場合。

まず、 smallrye-jwt の依存関係を追加することから始めます。

pom.xml
<dependency>
    <groupId>io.smallrye</groupId>
    <artifactId>smallrye-jwt</artifactId>
</dependency>
build.gradle
implementation("io.smallrye:smallrye-jwt")

さらに、 application.properties を更新して、 smallrye-jwt によって提供されるすべての CDI プロデューサーを次のように含めます。

quarkus.index-dependency.smallrye-jwt.group-id=io.smallrye
quarkus.index-dependency.smallrye-jwt.artifact-id=smallrye-jwt

設定リファレンス

Quarkus の設定

ビルド時に固定される設定プロパティー - 他のすべての設定プロパティーは実行時にオーバーライド可能

Configuration property

デフォルト

The MP-JWT configuration object

Environment variable: QUARKUS_SMALLRYE_JWT_ENABLED

Show more

boolean

true

The name of the java.security.Provider that supports SHA256withRSA signatures

Environment variable: QUARKUS_SMALLRYE_JWT_RSA_SIG_PROVIDER

Show more

string

SunRsaSign

Enable this property if fetching the remote keys can be a time-consuming operation. Do not enable it if you use the local keys.

Environment variable: QUARKUS_SMALLRYE_JWT_BLOCKING_AUTHENTICATION

Show more

boolean

'true' if 'mp.jwt.decrypt.key.location' or 'mp.jwt.verify.publickey.location' location is set and the location uses the HTTP or HTTPS protocol

Always create HTTP 401 challenge, even for requests containing no authentication credentials. JWT authentication mechanism will return HTTP 401 when an authentication challenge is required. However if it is used alongside one of the interactive authentication mechanisms then returning HTTP 401 to the users accessing the application from a browser may not be desired. If you prefer you can request that JWT authentication mechanism does not create a challenge in such cases by setting this property to 'true'.

Environment variable: QUARKUS_SMALLRYE_JWT_SILENT

Show more

boolean

false

JWT authentication mechanism priority.

Environment variable: QUARKUS_SMALLRYE_JWT_PRIORITY

Show more

int

1000

MicroProfile JWT の設定

プロパティ名 デフォルト 説明

mp.jwt.verify.publickey

なし

mp.jwt.verify.publickey 設定プロパティーを使用すると、公開鍵テキストを文字列として提供できます。公開鍵は、サポートされている公開鍵形式 セクションで定義された順序で、提供された文字列から解析されます。

mp.jwt.verify.publickey.location

なし

設定プロパティーでは、公開鍵の外部または内部の場所を指定できます。値は、相対パスまたは URL を使用できます。値が HTTPS ベースの JWK セットを指している場合、ネイティブモードで動作させるには、 quarkus.ssl.native プロパティーも true に設定する必要があります。詳細は、ネイティブ実行可能ファイルでの SSL の使用 を参照してください。

mp.jwt.verify.publickey.algorithm

RS256

署名アルゴリズムのリスト。楕円曲線署名アルゴリズムをサポートするには、 ES256 に設定します。

mp.jwt.decrypt.key.location

なし

設定プロパティーを使用すると、秘密復号化キーの外部または内部の場所を指定できます。

mp.jwt.decrypt.key.algorithm

RSA-OAEPRSA-OAEP-256

復号アルゴリズムのリスト。 RSA-OAEP-256 に設定すると、SHA-256 のみの RSA-OAEP をサポートできます。

mp.jwt.verify.issuer

なし

設定プロパティーは、サーバーが有効として受け入れる JWT の iss (発行者) クレームの値を指定します。

mp.jwt.verify.audiences

なし

トークン aud クレームに含まれる可能性のあるオーディエンスのコンマ区切りリスト。

mp.jwt.verify.clock.skew

60

トークンの有効期限と年齢確認時に使用されるクロックスキュー(秒)。トークンの有効期限切れ後、現在時刻がこのプロパティーで指定された秒数以内であれば、期限切れのトークンは受理されます。デフォルト値は 60 秒です。

mp.jwt.verify.token.age

none

トークン iat (発行時刻) から経過してはならない秒数です。

mp.jwt.token.header

Authorization

Cookie などの別のヘッダーを使用してトークンを渡す場合は、このプロパティーを設定します。

mp.jwt.token.cookie

なし

トークンを含む Cookie の名前。このプロパティーは、 mp.jwt.token.headerCookie に設定されている場合にのみ有効です。

追加の SmallRye JWT 設定

SmallRye JWT は、トークン処理のカスタマイズに使用できるプロパティーを他にも提供します。

プロパティ名 デフォルト 説明

smallrye.jwt.verify.secretkey

なし

秘密鍵は文字列として提供されます。

smallrye.jwt.verify.key.location

なし

公開鍵と秘密鍵の両方を指すことができる検証鍵の場所。秘密鍵は JWK 形式でのみ使用できます。このプロパティーが設定されている場合、'mp.jwt.verify.publickey.location' は無視されることに注意してください。

smallrye.jwt.verify.algorithm

署名アルゴリズム。このプロパティーは、 HS256 などの対称アルゴリズムを設定する場合にのみ使用してください。 ES256 などの非対称アルゴリズムの設定には非推奨です。代わりに 'mp.jwt.verify.publickey.algorithm' を使用してください。

smallrye.jwt.verify.key-format

ANY

このプロパティーを PEM_KEYPEM_CERTIFICATEJWKJWK_BASE64URL などの特定のキー形式に設定して、検証鍵のロード方法を最適化します。

smallrye.jwt.verify.key-provider

DEFAULT

デフォルトでは、PEM、JWK、または JWK キーセットは、MicroProfile JWT 仕様で要求されているように、ローカルファイルシステムから読み取ったり、URI から取得したりできます。このプロパティーを AWS_ALB に設定して、AWS Application Load Balancer の検証キー解決をサポートします。

smallrye.jwt.verify.relax-key-validation

false

検証キーの検証を緩和します。このプロパティーを true に設定すると、長さが 2048 ビット未満の公開 RSA 鍵が許可されます。

smallrye.jwt.verify.certificate-thumbprint

false

このプロパティーが有効になっている場合、署名されたトークンには「x5t」または「x5t#S256」X509Certificate サムプリントヘッダーが含まれている必要があります。検証キーは JWK または PEM 証明書鍵形式のみ使用できます。JWK キーには「x5c」(Base64 でエンコードされた X509Certificate) プロパティーが設定されている必要があります。

smallrye.jwt.token.header

Authorization

Cookie などの別のヘッダーを使用してトークンを渡す場合は、このプロパティーを設定します。このプロパティーは非推奨です。「mp.jwt.token.header」を使用してください。

smallrye.jwt.key-cache-size

100

キーキャッシュのサイズ。smallrye.jwt.verify.key-provider=AWS_ALBAWS_ALB などのキープロバイダーが設定され、鍵を動的に解決する場合に、このプロパティーと smallrye.jwt.key-cache-time-to-live を使用してキーキャッシュを制御します。

smallrye.jwt.key-cache-time-to-live

10

キーキャッシュエントリーの有効期間 (分単位)。smallrye.jwt.verify.key-provider=AWS_ALBAWS_ALB などのキープロバイダーが設定され、鍵を動的に解決する場合に、このプロパティーと smallrye.jwt.key-cache-size を使用してキーキャッシュを制御します。

smallrye.jwt.token.cookie

なし

トークンを含む Cookie の名前。このプロパティーは、smallrye.jwt.token.headerCookie に設定されている場合にのみ有効です。このプロパティーは非推奨です。mp.jwt.token.cookie を使用してください。

smallrye.jwt.always-check-authorization

false

smallrye.jwt.token.headerCookie に設定されていても、smallrye.jwt.token.cookie という名前の Cookie が存在しない場合でも Authorization ヘッダーがチェックされるように、このプロパティーを true に設定します。

smallrye.jwt.token.schemes

Bearer

DPoP などの単一または複数の代替スキームを含むコンマ区切りのリスト。

smallrye.jwt.token.kid

なし

鍵の識別子。設定されている場合、検証 JWK キーとすべての JWT トークンには、一致する kid ヘッダーが必要です。

smallrye.jwt.time-to-live

なし

JWT を発行して使用できる最大秒数。実質的に、JWT の有効期限と発行日の差がこの値を超えてはなりません。このプロパティーを正でない値に設定すると、トークンが有効な「iat」(発行日) クレームを持つという要件が緩和されます。

smallrye.jwt.require.named-principal

true

アプリケーションが java.security.Principal が名前を返すことに依存している場合、トークンには upnpreferred_username、または sub クレームが設定されている必要があります。このプロパティーを設定すると、アプリケーションコードが null 以外の Principal 名を確実に処理するためにこれらのクレームのいずれも利用できない場合、SmallRye JWT は例外をスローします。

smallrye.jwt.path.sub

なし

件名を含むクレームへのパス。これは最上位の JSON オブジェクトから始まり、各セグメントが JSON オブジェクト名のみを表す複数のセグメントを含めることができます (例: realms/subject)。このプロパティーは、トークンに「sub」クレームがないが、サブジェクトが別のクレームに設定されている場合に使用できます。名前空間修飾クレームには二重引用符を使用します。

smallrye.jwt.claims.sub

なし

現在のトークンに使用可能な標準またはカスタムの sub クレームがない場合に、このプロパティーを使用して、デフォルトのサブクレーム値を設定できます。事実上、 upnpreferred_usernamesub クレームが設定されていない場合、このプロパティーを使用して java.security.Principal 名をカスタマイズできます。

smallrye.jwt.path.groups

なし

グループを含むクレームへのパス。これは最上位の JSON オブジェクトから始まり、各セグメントが JSON オブジェクト名のみを表す複数のセグメントを含めることができます (例: realm/groups)。このプロパティーは、トークンに「groups」クレームがないが、グループが別のクレームに設定されている場合に使用できます。名前空間修飾クレームには二重引用符を使用します。

smallrye.jwt.groups-separator

space

複数のグループ値を含む可能性のある文字列を分割するためのセパレーター。これは、smallrye.jwt.path.groups プロパティーが文字列値を持つカスタムクレームを指している場合にのみ使用されます。標準の OAuth2 scope クレームにはスペースで区切られたシーケンスが含まれる可能性があるため、デフォルト値は単一のスペースです。

smallrye.jwt.claims.groups

なし

現在のトークンに使用可能な標準またはカスタムのグループクレームがない場合に、このプロパティーを使用してデフォルトのグループクレーム値を設定できます。

smallrye.jwt.jwks.refresh-interval

60

JWK キャッシュの更新間隔 (分単位)。mp.jwt.verify.publickey.location が HTTP または HTTPS URL ベースの JWK セットを指し、JWK HTTPS エンドポイントから正の max-age パラメーター値を持つ HTTP Cache-Control レスポンスヘッダーが返されない限り、無視されます。

smallrye.jwt.jwks.forced-refresh-interval

30

強制 JWK キャッシュ更新間隔 (分単位)。これは、キャッシュに現在のトークンの kid ヘッダーと一致する kid プロパティーを持つ JWK キーがないためにトークンの検証が失敗した場合に発生する可能性がある強制更新の試行頻度を制限するために使用されます。mp.jwt.verify.publickey.location が HTTP または HTTPS URL ベースの JWK セットを指していない限り、無視されます。

smallrye.jwt.expiration.grace

0

有効期限を秒単位で指定します。デフォルトでは、現在時刻がトークンの有効期限から 1 分以内であれば、期限切れのトークンはまだ受け入れられます。このプロパティーは非推奨です。代わりに mp.jwt.verify.clock.skew を使用してください。

smallrye.jwt.verify.aud

なし

トークン aud クレームに含まれる可能性のあるオーディエンスのコンマ区切りリスト。このプロパティーは非推奨です。mp.jwt.verify.audiences を使用してください。

smallrye.jwt.required.claims

なし

トークンに含める必要があるクレームのコンマ区切りリスト。

smallrye.jwt.decrypt.key.location

なし

秘密復号鍵の外部または内部の場所を指定するための設定プロパティー。このプロパティーは非推奨です。 mp.jwt.decrypt.key.location を使用してください。

smallrye.jwt.decrypt.algorithm

RSA_OAEP

復号化アルゴリズム。

smallrye.jwt.decrypt.key

なし

文字列として提供される復号化キー。

smallrye.jwt.token.decryption.kid

なし

復号化キー識別子。設定されている場合、復号化 JWK キーとすべての JWT トークンには、一致する kid ヘッダーが必要です。

smallrye.jwt.client.tls.certificate.path

なし

鍵を HTTPS 経由で取得する必要がある場合に設定する必要がある可能性のある TLS 信頼済み証明書へのパス。

smallrye.jwt.client.tls.trust-all

false

すべてのホスト名を信頼します。キーを HTTPS 経由でフェッチする必要があり、このプロパティーが true に設定されている場合、デフォルトですべてのホスト名が信頼されます。

smallrye.jwt.client.tls.hosts

なし

信頼できるホスト名のセット。キーを HTTPS 経由でフェッチする必要があり、 smallrye.jwt.client.tls.trust-allfalse に設定されている場合、このプロパティーを使用して信頼できるホスト名を設定できます。

smallrye.jwt.http.proxy.host

なし

HTTP プロキシーホスト。

smallrye.jwt.http.proxy.port

80

HTTP プロキシーポート。

smallrye.jwt.keystore.type

JKS

このプロパティーは、 mp.jwt.verify.publickey.location または mp.jwt.decrypt.key.location のいずれかが KeyStore ファイルを指している場合に、キーストアタイプをカスタマイズするために使用できます。設定されていない場合は、ファイル名のチェックおよびキーストアタイプの決定が行われ、デフォルトで JKS に設定されます。

smallrye.jwt.keystore.provider

mp.jwt.verify.publickey.location または mp.jwt.decrypt.key.locationKeyStore ファイルを指している場合、このプロパティーを使用して KeyStore プロバイダーをカスタマイズできます。

smallrye.jwt.keystore.password

キーストアのパスワード。 mp.jwt.verify.publickey.location または mp.jwt.decrypt.key.location の場合は、このプロパティーを設定する必要があります。

smallrye.jwt.keystore.verify.key.alias

このプロパティーは、mp.jwt.verify.publickey.locationKeyStore ファイルを指している場合に、KeyStore から一致する証明書から抽出される公開検証鍵を識別するために設定する必要があります。

smallrye.jwt.keystore.decrypt.key.alias

このプロパティは、 mp.jwt.decrypt.key.locationKeyStore ファイルを指している場合、プライベートな復号鍵を特定するために設定する必要があります。

smallrye.jwt.keystore.decrypt.key.password

このプロパティーは、 mp.jwt.decrypt.key.locationKeyStore ファイルを指しているときに、 KeyStore 内の秘密復号化鍵のパスワードが smallrye.jwt.keystore.password と異なる場合に設定できます。

smallrye.jwt.resolve-remote-keys-at-startup

false

アプリケーションの起動時にリモート鍵を解決するには、このプロパティーを true に設定します。

関連コンテンツ