CLOVER🍀

That was when it all began.

QuarkusのOpenID Connect Extensionを試す(リソース保護のみ)

これは、なにをしたくて書いたもの?

QuarkusのExtensionに、OpenID Connect向けのものができていたようなので、ちょっと試してみようかなと。

Quarkus - Using OpenID Connect Adapter to Protect JAX-RS Applications

Quarkus 0.27.0を使います。

Quarkus OpenID Connect Extension

こちらのExtensionですね。

https://github.com/quarkusio/quarkus/tree/0.27.0/extensions/oidc

ガイドを参照すると、「bearer token authorization」でアプリケーションを保護するとあります。

This guide demonstrates how your Quarkus application can use an OpenID Connect Adapter to protect your JAX-RS applications using bearer token authorization, where these tokens are issued by OpenId Connect and OAuth 2.0 compliant Authorization Servers such as Keycloak.

Quarkus - Using OpenID Connect Adapter to Protect JAX-RS Applications

このガイドに書かれている内容と、試した感じだと、事前にアクセストークンを取得して、そのトークンを使ってアクセスすることを前提に
アプリケーションを保護するという使い方のようです。

このあたりですね。

Testing the Application

これは、認証???という気はしますが、そのあたりはこちらのガイドに記載があるようです。

Quarkus - Protecting Web Applications Using OpenID Connect

また、Keycloakの管理ポリシーを使うようにするExtensionもあります。

Keycloak Authorization Guide

が、いろいろあったので、今回はパス。あくまで、最初に記載したガイドの範囲で試すことにします。

QuarkusのOpenID Connect Adapterは、以下のモジュールがベースになっているようです。

The OAuth2 auth provider - Vert.x

また、QuarkusのSecurity Extensionにも統合されます。

https://github.com/quarkusio/quarkus/tree/0.27.0/extensions/security

また、CORSについては今回は扱いませんが、ガイドはこちら。

CORS filter

とまあ、前置きはこれくらいにして試してみましょう。

環境

今回の環境は、こちらです。

$ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~18.04.1-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)


$ mvn -version
Apache Maven 3.6.2 (40f52333136460af0dc0d7232c0dc0bcf0d9e117; 2019-08-28T00:06:16+09:00)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 1.8.0_222, vendor: Private Build, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-66-generic", arch: "amd64", family: "unix"


$ $GRAALVM_HOME/bin/native-image --version
GraalVM Version 19.2.1 CE

Keycloakは、7.0.1を使います。

2019-11-02 10:20:29,839 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Keycloak 7.0.1 (WildFly Core 9.0.2.Final) started in 20519ms - Started 589 of 884 services (601 services are lazy, passive or on-demand)

Keycloakは、172.17.0.2のIPアドレスで動作しているものとします。

Keycloakの管理ユーザーも作成。

$ bin/add-user-keycloak.sh -u keycloak-admin -p password
$ bin/jboss-cli.sh -c --command=reload

お題

Quarkus上で、REST APIを作成しますが、一部のAPIはアクセス可能なロールを絞ったり、認証必須にしたりします。

また、APIによっては、認証されているユーザーの情報(JWTクレーム・セット)を返すようにしたりしましょう。

Keycloak上には、以下の情報でRealmやユーザーを作成します。

  • Realm … demo-api
  • Client-Id … sample-rest-api
  • Role … users、adminsの2つ
  • User … user001(users Role)、admin001(admins Role)の2つ

これらの前提で、進めていきます。

サンプルアプリケーションの作成

まずは、プロジェクトを作成します。Extensionに「oidc」を加えておくことがポイントです。

$ mvn io.quarkus:quarkus-maven-plugin:0.27.0:create \
    -DprojectGroupId=org.littlewings \
    -DprojectArtifactId=resteasy-oidc \
    -Dextensions="oidc, resteasy-jackson"

$ cd resteasy-oidc

「resteasy-jackson」は、JSONを扱うためですが、JSON-BではなくJacksonにしたのはなんとなくです。

まずは、未認証状態でアクセスできるJAX-RSリソースクラスを作成。
src/main/java/org/littlewings/quarkus/oidc/AnonymousResource.java

package org.littlewings.quarkus.oidc;

import java.security.Principal;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import io.quarkus.security.identity.SecurityIdentity;

@Path("anonymous")
public class AnonymousResource {
    @Inject
    SecurityIdentity securityIdentity;

    @GET
    @Path("greeting")
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello World!!";
    }

    @GET
    @Path("user-info")
    @Produces(MediaType.APPLICATION_JSON)
    public Principal userInfo() {
        System.out.println(securityIdentity.getPrincipal().getClass().getName());
        return securityIdentity.getPrincipal();
    }
}

とりあえずメッセージを返すだけのリソースメソッドと、認証されていればユーザーの情報を返すメソッドを用意してみました。

ユーザーの情報にアクセスするためには、SecurityIdentityを使うようです。

    @Inject
    SecurityIdentity securityIdentity;


    @GET
    @Path("user-info")
    @Produces(MediaType.APPLICATION_JSON)
    public Principal userInfo() {
        System.out.println(securityIdentity.getPrincipal().getClass().getName());
        return securityIdentity.getPrincipal();
    }

SecurityIdentity#getPrincipalで、現在のユーザー情報にアクセスすることができます。

他にも、現在が匿名ユーザーであるかどうかだったり、ロールなどの確認もできます。

SecurityIdentityがどのようなインターフェースを持つかは、こちらで確認するとよいでしょう。

https://github.com/quarkusio/quarkus-security/blob/1.0.0.Beta1/src/main/java/io/quarkus/security/identity/SecurityIdentity.java

QuarkusのSecurity Extensionに、このインターフェースの実装があります。

https://github.com/quarkusio/quarkus/tree/0.27.0/extensions/security/runtime/src/main/java/io/quarkus/security/runtime

次。

users(またはadmins)ロールを持っていれば、アクセス可能なJAX-RSリソースクラス。
src/main/java/org/littlewings/quarkus/oidc/UsersResource.java

package org.littlewings.quarkus.oidc;

import java.security.Principal;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import io.quarkus.security.identity.SecurityIdentity;

@Path("users")
public class UsersResource {
    @Inject
    SecurityIdentity securityIdentity;

    @GET
    @Path("user-info")
    @RolesAllowed({"users", "admins"})
    @Produces(MediaType.APPLICATION_JSON)
    public Principal userInfo() {
        return securityIdentity.getPrincipal();
    }
}

今回は、users、admins両方アクセス可能にしています。

    @RolesAllowed({"users", "admins"})

@RolesAllowedアノテーションは、Java EEで定義されているものであり、クラスまたはメソッドに付与することができます。

RolesAllowed (Java(TM) EE 7 Specification APIs)

次。

adminsロールのみ、許可するリソース。
src/main/java/org/littlewings/quarkus/oidc/AdminsResource.java

package org.littlewings.quarkus.oidc;

import java.security.Principal;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import io.quarkus.security.identity.SecurityIdentity;

@Path("admins")
public class AdminsResource {
    @Inject
    SecurityIdentity securityIdentity;

    @GET
    @Path("user-info")
    @RolesAllowed("admins")
    @Produces(MediaType.APPLICATION_JSON)
    public Principal userInfo() {
        return securityIdentity.getPrincipal();
    }
}

最後に、認証されている時のみアクセス可能なJAX-RSリソースクラス。
src/main/java/org/littlewings/quarkus/oidc/AuthenticatedResource.java

package org.littlewings.quarkus.oidc;

import java.security.Principal;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;

@Path("authenticated")
public class AuthenticatedResource {
    @Inject
    SecurityIdentity securityIdentity;

    @GET
    @Path("user-info")
    @Authenticated
    @Produces(MediaType.APPLICATION_JSON)
    public Principal guardedUserInfo() {
        return securityIdentity.getPrincipal();
    }
}

この場合は、@Authenticatedアノテーションを使用します。@AuthenticatedアノテーションはQuarkusが提供するもので、こちらも
クラスおよびメソッドに付与することができます。

https://github.com/quarkusio/quarkus-security/blob/1.0.0.Beta1/src/main/java/io/quarkus/security/Authenticated.java

設定は、最低限の項目にしました。
src/main/resources/application.properties

quarkus.oidc.auth-server-url=http://172.17.0.2:8080/auth/realms/demo-api
quarkus.oidc.client-id=sample-rest-api

OpenID Connectの認証ProviderへのアクセスURLと、Client IDがあれば利用することができます。

設定項目は、こちら。

Configuring using the application.properties file

というか、この使い方だとClient Secretすら要りません…。

これら2つを設定しなかった場合は、アプリケーションがうまく動作しなくなります。

auth-server-urlを未定義にした場合。

java.lang.RuntimeException: java.net.MalformedURLException: no protocol: /.well-known/openid-configuration
    at io.vertx.ext.auth.oauth2.impl.OAuth2API.makeRequest(OAuth2API.java:112)
    at io.vertx.ext.auth.oauth2.providers.OpenIDConnectAuth.discover(OpenIDConnectAuth.java:42)
    at io.vertx.ext.auth.oauth2.providers.KeycloakAuth.discover(KeycloakAuth.java:120)
    at io.quarkus.oidc.runtime.OidcRecorder.setup(OidcRecorder.java:49)
    at io.quarkus.deployment.steps.OidcBuildStep$setup24.deploy_0(OidcBuildStep$setup24.zig:92)
    at io.quarkus.deployment.steps.OidcBuildStep$setup24.deploy(OidcBuildStep$setup24.zig:36)
    at io.quarkus.runner.ApplicationImpl1.doStart(ApplicationImpl1.zig:137)
    at io.quarkus.runtime.Application.start(Application.java:94)
    at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:143)
    at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:176)
    at io.quarkus.dev.DevModeMain.start(DevModeMain.java:94)
    at io.quarkus.dev.DevModeMain.main(DevModeMain.java:66)
Caused by: java.net.MalformedURLException: no protocol: /.well-known/openid-configuration
    at java.net.URL.<init>(URL.java:600)
    at java.net.URL.<init>(URL.java:497)
    at java.net.URL.<init>(URL.java:446)
    at io.vertx.ext.auth.oauth2.impl.OAuth2API.makeRequest(OAuth2API.java:93)
    ... 11 more

client-idを未定義にした場合。

Caused by: java.lang.IllegalArgumentException: Configuration missing. You need to specify [clientId]
    at io.vertx.ext.auth.oauth2.impl.flow.AbstractOAuth2Flow.throwIfNull(AbstractOAuth2Flow.java:48)
    at io.vertx.ext.auth.oauth2.impl.flow.AuthCodeImpl.<init>(AuthCodeImpl.java:39)
    at io.vertx.ext.auth.oauth2.impl.OAuth2AuthProviderImpl.<init>(OAuth2AuthProviderImpl.java:68)
    at io.vertx.ext.auth.oauth2.OAuth2Auth.create(OAuth2Auth.java:132)
    at io.vertx.ext.auth.oauth2.providers.OpenIDConnectAuth.lambda$discover$1(OpenIDConnectAuth.java:79)
    at io.vertx.ext.auth.oauth2.impl.OAuth2API.lambda$null$1(OAuth2API.java:129)
    at io.vertx.core.http.impl.HttpClientResponseImpl$BodyHandler.notifyHandler(HttpClientResponseImpl.java:292)
    at io.vertx.core.http.impl.HttpClientResponseImpl.lambda$bodyHandler$0(HttpClientResponseImpl.java:193)
    at io.vertx.core.http.impl.HttpClientResponseImpl.handleEnd(HttpClientResponseImpl.java:248)
    ... 35 more

確認する

では、動かして確認してみましょう。

パッケージングして起動。

$ mvn package
$ java -jar target/resteasy-oidc-1.0-SNAPSHOT-runner.jar

起動すると、Security ExtensionやVert.x Extensionも有効になっていることがわかります。

2019-11-02 20:35:41,365 INFO  [io.quarkus] (main) Installed features: [cdi, oidc, resteasy, resteasy-jackson, security, vertx]

では、ドキュメントに沿って試してみましょう。

Testing the Application

まずは、未認証状態でアクセス。

$ curl localhost:8080/anonymous/greeting
Hello World!!

ユーザー情報を取得しようとしてみます。

$ curl localhost:8080/anonymous/user-info
{"name":""}

無名のユーザーみたいです。

この時の、Principalは以下のようです。

io.quarkus.security.runtime.AnonymousIdentityProvider$1

ソースコードは、こちらですね。

https://github.com/quarkusio/quarkus/blob/0.27.0/extensions/security/runtime/src/main/java/io/quarkus/security/runtime/AnonymousIdentityProvider.java#L19

SecurityIdentityも、それっぽいのがあります。

https://github.com/quarkusio/quarkus/blob/0.27.0/extensions/security/runtime/src/main/java/io/quarkus/security/runtime/AnonymousIdentityProvider.java#L26

ロールでアクセス権限を制限したり、認証必須にしているリソースメソッドに対しては、すべてHTTPステータスコード401が返ってきます。

$ curl -i localhost:8080/users/user-info
HTTP/1.1 401 Unauthorized
Content-Length: 0


$ curl -i localhost:8080/admins/user-info
HTTP/1.1 401 Unauthorized
Content-Length: 0


$ curl -i localhost:8080/authenticated/user-info
HTTP/1.1 401 Unauthorized
Content-Length: 0

ちなみに、認証サーバーへリダイレクト、ということにはならないようです。
※これをやりたかったら、続きのガイド…みたいなのですが…

では、Keycloakから、アクセストークンを取得してみます。

まずは、user001から。

$ access_token=$( \
curl -X POST http://172.17.0.2:8080/auth/realms/demo-api/protocol/openid-connect/token \
    --user sample-rest-api:client-secret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=user001&password=password&grant_type=password' | jq --raw-output '.access_token' \
)

取得したアクセストークンを使って、ユーザー情報を取得してみます。最初に、認証やロールの制限をかけていないリソースメソッドから。

$ curl localhost:8080/anonymous/user-info -H "Authorization: Bearer "$access_token
{"rawToken":null,"claims":{"claimsMap":{"jti":"3026f20d-76be-4676-a5a9-d6e3535da1c8","exp":1572699465,"nbf":0,"iat":1572699165,"iss":"http://172.17.0.2:8080/auth/realms/demo-api","aud":"account","sub":"f4a47f71-c5c3-4364-920e-58b284df1523","typ":"Bearer","azp":"sample-rest-api","auth_time":0,"session_state":"78ebf1fc-247a-4f80-a56f-1c53b681fc2f","acr":"1","allowed-origins":[{"string":"http://localhost:8080","valueType":"STRING","chars":"http://localhost:8080"}],"realm_access":{"roles":[{"string":"offline_access","valueType":"STRING","chars":"offline_access"},{"string":"uma_authorization","valueType":"STRING","chars":"uma_authorization"},{"string":"users","valueType":"STRING","chars":"users"}]},"resource_access":{"account":{"roles":[{"string":"manage-account","valueType":"STRING","chars":"manage-account"},{"string":"manage-account-links","valueType":"STRING","chars":"manage-account-links"},{"string":"view-profile","valueType":"STRING","chars":"view-profile"}]}},"scope":"profile email","email_verified":false,"preferred_username":"user001"},"rawJson":"{\"jti\":\"3026f20d-76be-4676-a5a9-d6e3535da1c8\",\"exp\":1572699465,\"nbf\":0,\"iat\":1572699165,\"iss\":\"http://172.17.0.2:8080/auth/realms/demo-api\",\"aud\":\"account\",\"sub\":\"f4a47f71-c5c3-4364-920e-58b284df1523\",\"typ\":\"Bearer\",\"azp\":\"sample-rest-api\",\"auth_time\":0,\"session_state\":\"78ebf1fc-247a-4f80-a56f-1c53b681fc2f\",\"acr\":\"1\",\"allowed-origins\":[\"http://localhost:8080\"],\"realm_access\":{\"roles\":[\"offline_access\",\"uma_authorization\",\"users\"]},\"resource_access\":{\"account\":{\"roles\":[\"manage-account\",\"manage-account-links\",\"view-profile\"]}},\"scope\":\"profile email\",\"email_verified\":false,\"preferred_username\":\"user001\"}","notBefore":{"value":0,"valueInMillis":0},"issuedAt":{"value":1572699165,"valueInMillis":1572699165000},"jwtId":"3026f20d-76be-4676-a5a9-d6e3535da1c8","expirationTime":{"value":1572699465,"valueInMillis":1572699465000},"issuer":"http://172.17.0.2:8080/auth/realms/demo-api","audience":["account"],"subject":"f4a47f71-c5c3-4364-920e-58b284df1523","claimNames":["jti","exp","nbf","iat","iss","aud","sub","typ","azp","auth_time","session_state","acr","allowed-origins","realm_access","resource_access","scope","email_verified","preferred_username"]},"audience":["account"],"groups":[],"claimNames":["sub","resource_access","email_verified","allowed-origins","raw_token","iss","typ","preferred_username","aud","acr","nbf","realm_access","azp","auth_time","scope","exp","session_state","iat","jti"],"name":"user001","expirationTime":1572699465,"issuer":"http://172.17.0.2:8080/auth/realms/demo-api","subject":"f4a47f71-c5c3-4364-920e-58b284df1523","tokenID":"3026f20d-76be-4676-a5a9-d6e3535da1c8","issuedAtTime":1572699165}

長いので、ユーザー名を絞って取得してみましょう。

$ curl -s localhost:8080/anonymous/user-info -H "Authorization: Bearer "$access_token | jq --raw-output '.name'
user001

OKそうです。

なお、この時のPrincipalは、以下のようになります。

io.quarkus.oidc.runtime.OidcJwtCallerPrincipal

こちらですね。

https://github.com/quarkusio/quarkus/blob/0.27.0/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcJwtCallerPrincipal.java

users(およびadmins)ロールでアクセス制限をかけているリソースメソッドおよび、認証のみ制限をかけたリソースメソッドには
アクセスすることができます。

$ curl -s localhost:8080/users/user-info -H "Authorization: Bearer "$access_token | jq --raw-output '.name'
user001


$ curl -s localhost:8080/authenticated/user-info -H "Authorization: Bearer "$access_token | jq --raw-output '.name'
user001

adminsロールのみアクセス可能なリソースメソッドに対しては、HTTPステータスコード403となります。

$ curl -i localhost:8080/admins/user-info -H "Authorization: Bearer "$access_token
HTTP/1.1 403 Forbidden
content-length: 0

では、今度はadmin001ユーザーに切り替えます。

$ access_token=$( \
curl -X POST http://172.17.0.2:8080/auth/realms/demo-api/protocol/openid-connect/token \
    --user sample-rest-api:client-secret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=admin001&password=password&grant_type=password' | jq --raw-output '.access_token' \
)

この場合、いずれのリソースメソッドにもアクセスできるようになります。

$ curl -s localhost:8080/anonymous/user-info -H "Authorization: Bearer "$access_token | jq --raw-output '.name'
admin001


$ curl -s localhost:8080/users/user-info -H "Authorization: Bearer "$access_token | jq --raw-output '.name'
admin001


$ curl -s localhost:8080/admins/user-info -H "Authorization: Bearer "$access_token | jq --raw-output '.name'
admin001


$ curl -s localhost:8080/authenticated/user-info -H "Authorization: Bearer "$access_token | jq --raw-output '.name'
admin001

ネイティブイメージで実行する場合は、こちら。

$ mvn -P native package
$ ./target/resteasy-oidc-1.0-SNAPSHOT-runner

結果は、変わらず…と言いたいところですが、先ほどのコードだとPrincipalのJSONシリアライズに失敗するので、各リソースクラスに
メソッドを追加しました…。

Principal#getNameの結果だけを返すメソッドで。

@Path("anonymous")
public class AnonymousResource {

    /* 省略 */

    @GET
    @Path("name")
    @Produces(MediaType.TEXT_PLAIN)
    public String name() {
        return securityIdentity.getPrincipal().getName();
    }
}


@Path("users")
public class UsersResource {

    /* 省略 */

    @GET
    @Path("name")
    @RolesAllowed({"users", "admins"})
    @Produces(MediaType.TEXT_PLAIN)
    public String name() {
        return securityIdentity.getPrincipal().getName();
    }
}


@Path("admins")
public class AdminsResource {

    /* 省略 */

    @GET
    @Path("name")
    @RolesAllowed("admins")
    @Produces(MediaType.TEXT_PLAIN)
    public String name() {
        return securityIdentity.getPrincipal().getName();
    }
}


@Path("authenticated")
public class AuthenticatedResource {

    /* 省略 */

    @GET
    @Path("name")
    @Authenticated
    @Produces(MediaType.TEXT_PLAIN)
    public String name() {
        return securityIdentity.getPrincipal().getName();
    }
}

こちらを使って、確認するようにしました。

未認証状態。

$ curl -i localhost:8080/anonymous/name
HTTP/1.1 200 OK
Content-Length: 0
Content-Type: text/plain;charset=UTF-8


$ curl -i localhost:8080/users/name
HTTP/1.1 401 Unauthorized
Content-Length: 0


$ curl -i localhost:8080/admins/name
HTTP/1.1 401 Unauthorized
Content-Length: 0


$ curl -i localhost:8080/authenticated/name
HTTP/1.1 401 Unauthorized
Content-Length: 0

user001でアクセス。

access_token=$( \
curl -X POST http://172.17.0.2:8080/auth/realms/demo-api/protocol/openid-connect/token \
    --user sample-rest-api:client-secret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=user001&password=password&grant_type=password' | jq --raw-output '.access_token' \
)


$ curl localhost:8080/anonymous/name -H "Authorization: Bearer "$access_token
user001


$ curl localhost:8080/users/name -H "Authorization: Bearer "$access_token
user001


$ curl localhost:8080/authenticated/name -H "Authorization: Bearer "$access_token
user001


$ curl -i localhost:8080/admins/name -H "Authorization: Bearer "$access_token
HTTP/1.1 403 Forbidden
Content-Length: 9
Content-Type: text/plain;charset=UTF-8

Forbidden

admin001でアクセス。

access_token=$( \
curl -X POST http://172.17.0.2:8080/auth/realms/demo-api/protocol/openid-connect/token \
    --user sample-rest-api:client-secret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=admin001&password=password&grant_type=password' | jq --raw-output '.access_token' \
)


$ curl localhost:8080/anonymous/name -H "Authorization: Bearer "$access_token
admin001


$ curl localhost:8080/users/name -H "Authorization: Bearer "$access_token
admin001


$ curl localhost:8080/admins/name -H "Authorization: Bearer "$access_token
admin001


$ curl localhost:8080/authenticated/name -H "Authorization: Bearer "$access_token
admin001

ちょっとソースコードを変えてしまいましたが、認証の有無やロールによる動作が同じことは確認できました、と。

もう少し、コードを追う

OpenID Connect Extensionを追加したQuarkusは、起動時に認証サーバーを探しにいきます。

このあたりですね。処理に使われているクラス名だけ見ると、Keycloak…?

https://github.com/quarkusio/quarkus/blob/0.27.0/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java#L49

また、@RolesAllowedや@Authenticatedアノテーションを付与すると、インターセプターが起動します。

ここにありますね。

https://github.com/quarkusio/quarkus/tree/0.27.0/extensions/security/runtime/src/main/java/io/quarkus/security/runtime/interceptor

他のアノテーションとしては、@DenyAll、@PermitAllがあるようです。

また、インターセプター内から呼び出され、トークンの情報に対して、認証・認可に関する確認を行っているのはこちらのクラスです。

https://github.com/quarkusio/quarkus/blob/0.27.0/extensions/security/runtime/src/main/java/io/quarkus/security/runtime/interceptor/SecurityConstrainer.java

自分で作成するプログラム内で、こういったことをやりたい場合はSecurityIdentityを使ってif文などを書いたりすることになるのでしょう。

https://github.com/quarkusio/quarkus-security/blob/1.0.0.Beta1/src/main/java/io/quarkus/security/identity/SecurityIdentity.java

まとめ

QuarkusのOpenID Connect Extensionを、リソース保護のみですが、試してみました。

未認証状態でアクセスしたら、Keycloakのログインページにリダイレクトされたりして欲しいのですが、そのあたりはまた今度
確認してみようと思います。

このあたりを見ることになると思います。

Quarkus - Protecting Web Applications Using OpenID Connect

が、今は少し早そうです。