JWT RBAC の使用
このガイドでは、Quarkusアプリケーションが SmallRye JWT を利用して、 JSON Web Token を検証し、MicroProfile JWT org.eclipse.microprofile.jwt.JsonWebToken として表現し、Bearer Token Authorizationと Role-Based Access Control を使用してQuarkus HTTPエンドポイントへのセキュアなアクセスを提供する方法について説明します。
Quarkus OpenId Connect quarkus-oidc エクステンションは、ベアラートークン認可もサポートしており、 smallrye-jwt を使用してベアラートークンを JsonWebToken として表現します。詳しくは Using OpenID Connect to Protect Service Applications ガイドをご覧ください。OpenId Connect extensionは、QuarkusアプリケーションがOIDC Authorization Code Flowを使用してユーザーを認証する必要がある場合に使用する必要があります。詳しくは Using OpenID Connect to Protect Web Applications ガイドをご覧ください。
|
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 11+ がインストールされ、
JAVA_HOMEが適切に設定されていること -
Apache Maven 3.8.6
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
クイックスタート
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、すぐに完成した例に飛んでも構いません。
Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.git 、 アーカイブ をダウンロードします。
ソリューションは security-jwt-quickstart directory にあります。
Mavenプロジェクトの作成
まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。
このコマンドは、RESTエンドポイントを持つMavenプロジェクトを生成し、MicroProfile JWT RBAC サポートを含む smallrye-jwt エクステンションをインポートします。
すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリーで以下のコマンドを実行することで、プロジェクトに smallrye-jwt エクステンションを追加することができます。
quarkus extension add 'smallrye-jwt,smallrye-jwt-build'
./mvnw quarkus:add-extension -Dextensions='smallrye-jwt,smallrye-jwt-build'
./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>
implementation("io.quarkus:quarkus-smallrye-jwt")
implementation("io.quarkus:quarkus-smallrye-jwt-build")
JAX-RSのリソース調査
RESTエンドポイントを src/main/java/org/acme/security/jwt/TokenSecuredResource.java に以下の内容で作成します。
package org.acme.security.jwt;
import java.security.Principal;
import javax.annotation.security.PermitAll;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.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 | ここでは、現在認証されているトークンに関連付けられたクレームへのアクセスを提供する java.security.Principal インターフェイスのエクステンションである JsonWebToken インターフェイスを挿入します。 |
| 2 | @PermitAll は、JSR 250 の一般的なセキュリティーアノテーションであり、認証されているかどうかに関係なく、特定のエンドポイントにすべての呼び出し元がアクセスできることを示します。 |
| 3 | ここでは、JAX-RS SecurityContext を挿入して呼び出しのセキュリティー状態を検査し、 getResponseString() 関数を使用してレスポンス文字列を入力します。 |
| 4 | ここでは、リクエストのユーザー/呼び出し元の Principal を null と照合して、呼び出しが安全でないかどうかを確認します。 |
| 5 | ここでは、JsonWebToken が現在の Principal を表しているため、Principal と JsonWebToken が同じ名前であることを確認します。 |
| 6 | ここで、Principal の名前を取得します。 |
| 7 | 構築した応答では、呼び出し元の名前、リクエスト SecurityContext の isSecure() と getAuthenticationScheme() の状態、null 以外の JsonWebToken が挿入されたかどうかを利用します。 |
アプリケーションの実行
これで、アプリケーションを実行する準備が整いました。以下を使用してください。
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
次のような出力が得られるはずです。
[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, resteasy-reactive, resteasy-reactive-jackson, security, smallrye-context-propagation, smallrye-jwt, vertx, vertx-web]
REST エンドポイントが実行されているので、curl のようなコマンドラインツールを使ってアクセスすることができます。
$ curl http://127.0.0.1:8080/secured/permit-all; echo
hello + anonymous, isHttps: false, authScheme: null, hasJWT: false
このリクエストではJWTを設定していませんので、エンドポイントから見たセキュリティーステートがあるとは期待できず、レスポンスもそれに沿ったものとなっています。
-
ユーザー名は anonymous (匿名) です。
-
isHttps は https を使用しないので false です。
-
authScheme は null です。
-
hasJWTは false です。
Ctrl-Cを使用してQuarkusサーバーを停止します。
では実際に何かをセキュア化してみましょう。下記の新しいエンドポイントメソッド helloRolesAllowed を見てみましょう。
package org.acme.security.jwt;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;
import org.eclipse.microprofile.jwt.JsonWebToken;
@Path("/secured")
@RequestScoped
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 | ここでは、 JsonWebToken を挿入します。 |
| 2 | この新しいエンドポイントは /secured/roles-allowed に存在します。 |
| 3 | @RolesAllowed は、"User" または "Admin" ロールが割り当てられている場合は呼び出し元が特定のエンドポイントにアクセスできることを示す JSR 250 の一般的なセキュリティーアノテーションです。 |
| 4 | ここでは、 hello メソッドと同じ方法で応答を作成しますが、挿入された JsonWebToken を直接呼び出すことで JWT birthdate クレームの値を追加します。 |
TokenSecuredResource にこの追加を行った後、 ./mvnw compile quarkus:dev コマンドを再実行してから、 curl -v http://127.0.0.1:8080/secured/roles-allowed; echo を試行して新規エンドポイントへのアクセスを試みてください。出力は次のようになります。
$ 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
Not authorized
素晴らしいですね。リクエストに JWT トークンを提供していないため、エンドポイントにはアクセスできないはずであり、実際にアクセスできませんでした。代わりに HTTP 401 Unauthorized エラーを受け取りました。エンドポイントにアクセスするためには、有効な JWT を取得して渡す必要があります。これには 2 つのステップがあります。1) SmallRye JWT エクステンションに JWT の検証方法に関する情報を設定し、2) 適切なクレームを持つ適合する JWT を生成します。
SmallRye JWT エクステンションセキュリティー情報の設定
次の内容で security-jwt-quickstart/src/main/resources/application.properties を作成します。
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 の場所を指すように公開鍵の場所を設定しています。この鍵はパート B [公開鍵の追加] で追加します。 |
| 2 | 発行者を URL 文字列 https://example.com/issuer に設定しています。 |
| 3 | ネイティブ実行可能ファイルのリソースとして公開鍵を含めています。 |
公開鍵の追加
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 ファイルにコピーします。
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq
Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR
TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e
UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9
AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn
sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x
nQIDAQAB
-----END PUBLIC KEY-----
JWT の生成
多くの場合、 Keycloak などの ID マネージャーから JWT を取得しますが、このクイックスタートでは、 smallrye-jwt が提供する JWT 生成 API を使用して独自の JWT を生成します (詳細は SmallRye JWT を使用した JWT トークンの生成 を参照してください)。
次のリストからコードを取得し、 security-jwt-quickstart/src/test/java/org/acme/security/jwt/GenerateToken.java に配置します。
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;
public class GenerateToken {
/**
* Generate 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);
}
}
| 1 | iss クレームは JWT の発行者です。トークンが有効であると認められるためには、これがサーバー側の mp.jwt.verify.issuer と一致する必要があります。 |
| 2 | upn クレームは、MicroProfile JWT RBAC 仕様で、コンテナーセキュリティー API を介して表示される Principal に使用する優先クレームとして定義されています。 |
| 3 | group クレームは、JWT ベアラーに関連付けられたグループとトップレベルのロールを提供します。 |
| 4 | birthday クレームです。機密性の高いクレームと見なすことができるため、クレームの暗号化を検討したくなるかもしれません。 SmallRye JWT を使用した JWT トークンの生成 を参照してください。 |
このコードが機能するには、TokenSecuredResource アプリケーションにある公開鍵に対応する RSA 秘密鍵のコンテンツが必要であることに注意してください。次の PEM コンテンツを取得し、 security-jwt-quickstart/src/test/resources/privateKey.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 コマンド
秘密鍵を生成して PKCS#8 形式に変換するには、追加の手順が必要です。 秘密鍵を変換するための openssl コマンド
このクイックスタートで使用される鍵の代わりに、生成された鍵のペアを使用できます。 |
これで、 TokenSecuredResource エンドポイントで使用する JWT を生成できます。これを行うには、次のコマンドを実行します。
$ mvn exec:java -Dexec.mainClass=org.acme.security.jwt.GenerateToken -Dexec.classpathScope=test -Dsmallrye.jwt.sign.key.location=privateKey.pem
eyJraWQiOiJcL3ByaXZhdGVLZXkucGVtIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJqZG9lLXVzaW5nLWp3dC1yYmFjIiwiYXVkIjoidXNpbmctand0LXJiYWMiLCJ1cG4iOiJqZG9lQHF1YXJrdXMuaW8iLCJiaXJ0aGRhdGUiOiIyMDAxLTA3LTEzIiwiYXV0aF90aW1lIjoxNTUxNjU5Njc2LCJpc3MiOiJodHRwczpcL1wvcXVhcmt1cy5pb1wvdXNpbmctand0LXJiYWMiLCJyb2xlTWFwcGluZ3MiOnsiZ3JvdXAyIjoiR3JvdXAyTWFwcGVkUm9sZSIsImdyb3VwMSI6Ikdyb3VwMU1hcHBlZFJvbGUifSwiZ3JvdXBzIjpbIkVjaG9lciIsIlRlc3RlciIsIlN1YnNjcmliZXIiLCJncm91cDIiXSwicHJlZmVycmVkX3VzZXJuYW1lIjoiamRvZSIsImV4cCI6MTU1MTY1OTk3NiwiaWF0IjoxNTUxNjU5Njc2LCJqdGkiOiJhLTEyMyJ9.O9tx_wNNS4qdpFhxeD1e7v4aBNWz1FCq0UV8qmXd7dW9xM4hA5TO-ZREk3ApMrL7_rnX8z81qGPIo_R8IfHDyNaI1SLD56gVX-NaOLS2OjfcbO3zOWJPKR_BoZkYACtMoqlWgIwIRC-wJKUJU025dHZiNL0FWO4PjwuCz8hpZYXIuRscfFhXKrDX1fh3jDhTsOEFfu67ACd85f3BdX9pe-ayKSVLh_RSbTbBPeyoYPE59FW7H5-i8IE-Gqu838Hz0i38ksEJFI25eR-AJ6_PSUD0_-TV3NjXhF3bFIeT4VSaIZcpibekoJg0cQm-4ApPEcPLdgTejYHA-mupb8hSwg
JWT 文字列は Base64 URL でエンコードされた文字列で、'.' で区切られた 3 つのパートで構成されています。最初のパートは JWT ヘッダー、2 つ目のパートは JWT クレーム、3 つ目のパートは JWT シグネチャーです。
/secured/roles-allowed へのセキュリティーで保護されたアクセス
これを使用して、/secured/roles-allowed エンドポイントにセキュリティーで保護されたリクエストを作成しましょう。Quarkus サーバーが引き続き開発モードで実行されていることを確認してから、次のコマンドを実行し、前の手順で生成された自分の JWT バージョンを使用していることを確認します。
curl -H "Authorization: Bearer eyJraWQiOiJcL3ByaXZhdGVLZXkucGVtIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJqZG9lLXVzaW5nLWp3dC1yYmFjIiwiYXVkIjoidXNpbmctand0LXJiYWMiLCJ1cG4iOiJqZG9lQHF1YXJrdXMuaW8iLCJiaXJ0aGRhdGUiOiIyMDAxLTA3LTEzIiwiYXV0aF90aW1lIjoxNTUxNjUyMDkxLCJpc3MiOiJodHRwczpcL1wvcXVhcmt1cy5pb1wvdXNpbmctand0LXJiYWMiLCJyb2xlTWFwcGluZ3MiOnsiZ3JvdXAyIjoiR3JvdXAyTWFwcGVkUm9sZSIsImdyb3VwMSI6Ikdyb3VwMU1hcHBlZFJvbGUifSwiZ3JvdXBzIjpbIkVjaG9lciIsIlRlc3RlciIsIlN1YnNjcmliZXIiLCJncm91cDIiXSwicHJlZmVycmVkX3VzZXJuYW1lIjoiamRvZSIsImV4cCI6MTU1MTY1MjM5MSwiaWF0IjoxNTUxNjUyMDkxLCJqdGkiOiJhLTEyMyJ9.aPA4Rlc4kw7n_OZZRRk25xZydJy_J_3BRR8ryYLyHTO1o68_aNWWQCgpnAuOW64svPhPnLYYnQzK-l2vHX34B64JySyBD4y_vRObGmdwH_SEufBAWZV7mkG3Y4mTKT3_4EWNu4VH92IhdnkGI4GJB6yHAEzlQI6EdSOa4Nq8Gp4uPGqHsUZTJrA3uIW0TbNshFBm47-oVM3ZUrBz57JKtr0e9jv0HjPQWyvbzx1HuxZd6eA8ow8xzvooKXFxoSFCMnxotd3wagvYQ9ysBa89bgzL-lhjWtusuMFDUVYwFqADE7oOSOD4Vtclgq8svznBQ-YpfTHfb9QEcofMlpyjNA" http://127.0.0.1:8080/secured/roles-allowed; echo
$ curl -H "Authorization: Bearer eyJraWQ..." http://127.0.0.1:8080/secured/roles-allowed; echo
hello + jdoe@quarkus.io, isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13
成功! これで、以下が得られます
-
jdoe@quarkus.io という非匿名の発信者名
-
ベアラーの認証スキーム
-
非 null の JsonWebToken
-
birthdate クレームの値
JsonWebToken とクレーム挿入の使用
保護された REST エンドポイントにアクセスするための JWT を生成できるようになったので、 JsonWebToken インターフェイスと JWT クレームでさらに何ができるかを見てみましょう。 org.eclipse.microprofile.jwt.JsonWebToken インターフェイスは java.security.Principal インターフェイスを拡張します。実際、これは 前に使用した javax.ws.rs.core.SecurityContext#getUserPrincipal() 呼び出しにより返されるオブジェクトのタイプです。これは、CDI は使用しないが、REST コンテナー SecurityContext にアクセスできるコードは、 SecurityContext#getUserPrincipal() をキャストすることで、呼び出し元の JsonWebToken インターフェイスを取得できることを意味します。
JsonWebToken インターフェイスは、基盤となる JWT のクレームにアクセスするためのメソッドを定義します。これは、JWT に存在する可能性のある MicroProfile JWT RBAC 仕様および任意のクレームで必要な一般的クレームのアクセッサを提供します。。
すべての JWT クレームを挿入することもできます。 TokenSecuredResource を別のエンドポイント /secured/roles-allowed-admin で拡張してみましょう。これは、(JsonWebToken から取得するのではなく) 挿入された birthdate クレームを使用します。
package org.acme.security.jwt;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.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
public class TokenSecuredResource {
@Inject
JsonWebToken jwt; (1)
@Inject
@Claim(standard = Claims.birthdate)
String birthdate; (2)
@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; (3)
}
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 | ここでは、JsonWebToken を挿入します。 |
| 2 | ここでは、 birthday クレームを String として挿入します。これが @RequestScoped スコープが必要になった理由です。 |
| 3 | ここでは、挿入された birthday クレームを使用して、最終的な応答を作成します。 |
次に、トークンを再度生成して実行します。
curl -H "Authorization: Bearer eyJraWQiOiJcL3ByaXZhdGVLZXkucGVtIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJqZG9lLXVzaW5nLWp3dC1yYmFjIiwiYXVkIjoidXNpbmctand0LXJiYWMiLCJ1cG4iOiJqZG9lQHF1YXJrdXMuaW8iLCJiaXJ0aGRhdGUiOiIyMDAxLTA3LTEzIiwiYXV0aF90aW1lIjoxNTUxNjUyMDkxLCJpc3MiOiJodHRwczpcL1wvcXVhcmt1cy5pb1wvdXNpbmctand0LXJiYWMiLCJyb2xlTWFwcGluZ3MiOnsiZ3JvdXAyIjoiR3JvdXAyTWFwcGVkUm9sZSIsImdyb3VwMSI6Ikdyb3VwMU1hcHBlZFJvbGUifSwiZ3JvdXBzIjpbIkVjaG9lciIsIlRlc3RlciIsIlN1YnNjcmliZXIiLCJncm91cDIiXSwicHJlZmVycmVkX3VzZXJuYW1lIjoiamRvZSIsImV4cCI6MTU1MTY1MjM5MSwiaWF0IjoxNTUxNjUyMDkxLCJqdGkiOiJhLTEyMyJ9.aPA4Rlc4kw7n_OZZRRk25xZydJy_J_3BRR8ryYLyHTO1o68_aNWWQCgpnAuOW64svPhPnLYYnQzK-l2vHX34B64JySyBD4y_vRObGmdwH_SEufBAWZV7mkG3Y4mTKT3_4EWNu4VH92IhdnkGI4GJB6yHAEzlQI6EdSOa4Nq8Gp4uPGqHsUZTJrA3uIW0TbNshFBm47-oVM3ZUrBz57JKtr0e9jv0HjPQWyvbzx1HuxZd6eA8ow8xzvooKXFxoSFCMnxotd3wagvYQ9ysBa89bgzL-lhjWtusuMFDUVYwFqADE7oOSOD4Vtclgq8svznBQ-YpfTHfb9QEcofMlpyjNA" http://127.0.0.1:8080/secured/roles-allowed-admin; echo
$ curl -H "Authorization: Bearer eyJraWQ..." http://127.0.0.1:8080/secured/roles-allowed-admin; echo
hello + jdoe@quarkus.io, isHttps: false, authScheme: Bearer, hasJWT: true, birthdate: 2001-07-13
アプリケーションをパッケージ化して実行する
いつものように、アプリケーションは以下の方法でパッケージ化されます。
quarkus build
./mvnw install
./gradlew build
そして、 java -jar target/quarkus-app/quarkus-run.jar を使って実行されます。
$ java -jar target/quarkus-app/quarkus-run.jar
2019-03-28 14:27:48,839 INFO [io.quarkus] (main) Quarkus 2.16.12.Final started in 0.796s. Listening on: http://[::]:8080
2019-03-28 14:27:48,841 INFO [io.quarkus] (main) Installed features: [cdi, resteasy-reactive, resteasy-reactive-jackson, security, smallrye-jwt]
次のようにネイティブ実行可能ファイルを生成することもできます。
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.package.type=native
[INFO] Scanning for projects...
...
[security-jwt-quickstart-runner:25602] universe: 493.17 ms
[security-jwt-quickstart-runner:25602] (parse): 660.41 ms
[security-jwt-quickstart-runner:25602] (inline): 1,431.10 ms
[security-jwt-quickstart-runner:25602] (compile): 7,301.78 ms
[security-jwt-quickstart-runner:25602] compile: 10,542.16 ms
[security-jwt-quickstart-runner:25602] image: 2,797.62 ms
[security-jwt-quickstart-runner:25602] write: 988.24 ms
[security-jwt-quickstart-runner:25602] [total]: 43,778.16 ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 51.500 s
[INFO] Finished at: 2019-03-28T14:30:56-07:00
[INFO] ------------------------------------------------------------------------
$ ./target/security-jwt-quickstart-runner
2019-03-28 14:31:37,315 INFO [io.quarkus] (main) Quarkus 0.12.0 started in 0.006s. Listening on: http://[::]:8080
2019-03-28 14:31:37,316 INFO [io.quarkus] (main) Installed features: [cdi, resteasy-reactive, resteasy-reactive-jackson, security, smallrye-jwt]
ソリューションの探索
security-jwt-quickstart ディレクトリー にあるソリューションリポジトリーには、このクイックスタートガイドで使用したすべてのバージョンと、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 javax.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 注入要件 を参照してください。
サポートされている公開鍵形式
公開鍵には、優先順位に従って指定された次のいずれかの形式が適用さされます。
-
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 鍵 (JWK) または JSON Web 鍵セット (JWK セット) 形式のいずれかを使用して、この秘密鍵を表す必要があります。以下はその例です。
{
"keys": [
{
"kty":"oct",
"kid":"secretKey",
"k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"
}
]
}
この秘密鍵 JWK も、 smallrye.jwt.verify.key.location で参照する必要があります。 smallrye.jwt.verify.algorithm は HS256/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 を指定できます。
import javax.crypto.SecretKey;
import javax.ws.rs.GET;
import javax.ws.rs.core.NewCookie;
import javax.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 {
@Inject JWTParser parser;
private String secret = "AyM1SysPpbyDfgZld3umj1qzKObwVMko";
@GET
@Produces("text/plain")
public Response getUserName(@CookieParam("jwt") String jwtCookie) {
Response response = null;
if (jwtCookie == null) {
// Create a JWT token signed using the 'HS256' algorithm
String newJwtCookie = Jwt.upn("Alice").signWithSecret(secret);
// or create a JWT token encrypted 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();
}
}
}
SmallRye JWT を直接追加する方法 セクションで、 quarkus-smallrye-jwt によって提供される HTTP サポートなしで JWTParser を使用する方法についても参照してください。
トークン復号化
アプリケーションが、暗号化されたクレームまたは暗号化された内部署名クレームを含むトークンを受け入れる必要がある場合、復号化キーを指す 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 プリンシパルに変換するために使用されます。設定セクションにリストされている 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 javax.annotation.Priority;
import javax.enterprise.context.ApplicationScoped;
import javax.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());
}
}
}
トークンの伝播
下流サービスへのベアラアクセストークンの伝播については、トークン伝播 の項を参照してください。
テスト
Wiremock
HTTPS または HTTP ベースの JsonWebKey (JWK) セットを指すように mp.jwt.verify.publickey.location を設定する場合は、OpenID Connect Bearer トークン統合テスト の Wiremock セクションで説明したのと同じアプローチを使用できますが、その場合は代わりに MPJWT 設定プロパティーを使用するように application.properties を変更します。
# 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 を使用しており、さらに HTTPS または HTTP ベースの JsonWebKey (JWK) セットを指すように mp.jwt.verify.publickey.location を設定する場合は、OpenID Connect Bearer トークン統合テスト の Keycloak セクションで説明したのと同じアプローチを使用できますが、その場合は代わりに MPJWT 設定プロパティーを使用するように application.properties を変更します。
# 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 dockerコンテナとネットワークインターフェースを共有し、QuarkusアプリケーションとKeycloakが内部共有Dockerネットワーク経由で相互に通信することがあります。
そのような場合は、代わりに以下のような設定にしてください。
# keycloak.url is set by DevServices for Keycloak,
# Quarkus will access it via 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 トークン統合テスト の Local Public Key セクションで説明したのと同じアプローチを使用できますが、その場合は代わりに MPJWT 設定プロパティーを使用するように application.properties を変更します。
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 アノテーション
次の依存関係を追加します。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security-jwt</artifactId>
<scope>test</scope>
</dependency>
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 アノテーションはオプションであり、追加のトークンクレームを設定するために使用できます。
|
これは、同じセキュリティ設定のセットを複数のテストメソッドで使用する必要がある場合に特に便利です。 |
ログでエラーを確認する方法
トークンの検証または復号化エラーの詳細を確認するには、 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 を直接追加する方法
HTTP をサポートしない Quarkus エクステンション (たとえば Quarkus GRPC) を使用する、または quarkus-smallrye-jwt や Vert.x HTTP によって提供されるものと競合する独自のエクステンション固有の HTTP サポート (たとえば Quarkus Amazon Lambda) を提供する場合で、JWTParser を使用した JsonWebToken の解析と検証 を行う場合、 quarkus-smallrye-jwt の代わりに smallrye-jwt を直接使用してください。
次の依存関係を追加します。
<dependency>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-jwt</artifactId>
</dependency>
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 の設定
ビルド時に固定される設定プロパティ - 他のすべての設定プロパティは実行時にオーバーライド可能
タイプ |
デフォルト |
|
|---|---|---|
The MP-JWT configuration object Environment variable: Show more |
boolean |
|
The name of the Environment variable: Show more |
string |
|
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: Show more |
boolean |
|
MicroProfile JWT の設定
| プロパティ名 | デフォルト | 説明 |
|---|---|---|
|
|
|
|
|
Config プロパティーを使用すると、公開鍵の外部または内部の場所を指定できます。値は相対パスまたは URL の場合があります。値が HTTPS ベースの JWK セットを指している場合、ネイティブモードで機能するには、 |
|
|
署名アルゴリズム。 |
|
|
Config プロパティーを使用すると、秘密復号化鍵の外部または内部の場所を指定できます。 |
|
|
Config プロパティーは、サーバーが有効として受け入れる JWT の |
|
|
トークン |
|
|
|
|
|
トークンを含む Cookie の名前。このプロパティーは、 |
追加の SmallRye JWT 設定
SmallRye JWTには、トークン処理をカスタマイズするために使用できる、より多くのプロパティーが用意されています。
| プロパティ名 | デフォルト | 説明 |
|---|---|---|
|
|
公開鍵と秘密鍵の両方を指すことができる検証鍵の場所。秘密鍵は JWK 形式でのみ使用できます。このプロパティーが設定されている場合、'mp.jwt.verify.publickey.location' は無視されることに注意してください。 |
|
署名アルゴリズム。このプロパティーは、 |
|
|
|
このプロパティーを |
|
|
検証鍵の検証を緩和します。このプロパティーを |
|
|
このプロパティーが有効になっている場合、署名されたトークンには 'x5t' または 'x5t#S256' X509Certificatex5t 拇印ヘッダーが含まれている必要があります。この場合、検証鍵は JWK または PEM 証明書鍵形式でのみ使用できます。JWK 鍵には、'x5c' (Base64 でエンコードされた X509Certificate) プロパティーが設定されている必要があります。 |
|
|
|
|
|
トークンを含む Cookie の名前。このプロパティーは、 |
|
|
|
|
|
|
|
|
鍵の識別子。設定されている場合、検証 JWK 鍵とすべての JWT トークンには、一致する |
|
|
JWT を使用するために発行できる最大秒数。事実上、JWT の有効期限と発行日との差はこの値を超えてはなりません。このプロパティーを正でない値に設定すると、トークンが有効な 'iat' (で発行された) クレームを持つための要件が緩和されます。 |
|
|
アプリケーションが名前を返す |
|
|
件名を含むクレームへのパス。これはトップレベルの JSON オブジェクトから始まり、複数のセグメントを含めることができます。各セグメントは JSON オブジェクト名のみを表します (例: |
|
|
現在のトークンに使用可能な標準またはカスタムの |
|
|
グループを含むクレームへのパス。これはトップレベルの JSON オブジェクトから始まり、複数のセグメントを含めることができます。各セグメントは JSON オブジェクト名のみを表します (例: |
|
|
複数のグループ値を含む可能性のある文字列を分割するためのセパレーター。これは、 |
|
|
このプロパティーを使用して、現在のトークンに使用可能な標準またはカスタムのグループクレームがない場合に、デフォルトのグループクレーム値を設定できます。 |
|
|
JWK キャッシュの更新間隔 (分単位)。 |
|
|
強制 JWK キャッシュ更新間隔 (分単位)。現在のトークンの |
|
|
有効期限の猶予 (秒単位)。デフォルトでは、現在の時刻がトークンの有効期限から 1 分以内であれば、期限切れのトークンは引き続き受け入れられます。 |
|
|
トークン |
|
|
トークンに含める必要のあるクレームのコンマ区切りリスト。 |
|
|
Config プロパティーを使用すると、秘密復号化鍵の外部または内部の場所を指定できます。このプロパティーは推奨されません。'mp.jwt.decrypt.key.location' を使用してください。 |
|
|
復号化アルゴリズム。 |
|
|
文字列として提供される復号化キー。 |
|
|
復号化キー識別子。設定されている場合、復号化 JWK キーとすべての JWT トークンには、一致する |
|
|
キーを |
|
|
すべてのホスト名を信頼します。キーを |
|
|
信頼できるホスト名のセット。キーを |
|
|
HTTP プロキシーホスト。 |
|
|
HTTP プロキシーポート。 |
|
|
|
|
|
|
|
キーストアのパスワード。 |
|
|
このプロパティーは、 |
|
|
このプロパティは、 |
|
|
このプロパティは、 |