5.5. アプリケーションの作成
まず、/{tenant}
エンドポイントを実装します。以下のソースコードからわかるように、これは単なる通常の Jakarta REST リソースです。
package org.acme.quickstart.oidc; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import org.eclipse.microprofile.jwt.JsonWebToken; import io.quarkus.oidc.IdToken; @Path("/{tenant}") public class HomeResource { /** * Injection point for the ID Token issued by the OIDC provider. */ @Inject @IdToken JsonWebToken idToken; /** * Injection point for the Access Token issued by the OIDC provider. */ @Inject JsonWebToken accessToken; /** * Returns the ID Token info. * This endpoint exists only for demonstration purposes. * Do not expose this token in a real application. * * @return ID Token info */ @GET @Produces("text/html") public String getIdTokenInfo() { StringBuilder response = new StringBuilder().append("<html>") .append("<body>"); response.append("<h2>Welcome, ").append(this.idToken.getClaim("email").toString()).append("</h2>\n"); response.append("<h3>You are accessing the application within tenant <b>").append(idToken.getIssuer()).append(" boundaries</b></h3>"); return response.append("</body>").append("</html>").toString(); } /** * Returns the Access Token info. * This endpoint exists only for demonstration purposes. * Do not expose this token in a real application. * * @return Access Token info */ @GET @Produces("text/html") @Path("bearer") public String getAccessTokenInfo() { StringBuilder response = new StringBuilder().append("<html>") .append("<body>"); response.append("<h2>Welcome, ").append(this.accessToken.getClaim("email").toString()).append("</h2>\n"); response.append("<h3>You are accessing the application within tenant <b>").append(accessToken.getIssuer()).append(" boundaries</b></h3>"); return response.append("</body>").append("</html>").toString(); } }
受信リクエストからテナントを解決し、application.properties
内の特定の quarkus-oidc
テナント設定にマップするには、テナント設定を動的に解決できる io.quarkus.oidc.TenantConfigResolver
インターフェイスの実装を作成します。
package org.acme.quickstart.oidc; import jakarta.enterprise.context.ApplicationScoped; import org.eclipse.microprofile.config.ConfigProvider; import io.quarkus.oidc.OidcRequestContext; import io.quarkus.oidc.OidcTenantConfig; import io.quarkus.oidc.OidcTenantConfig.ApplicationType; import io.quarkus.oidc.TenantConfigResolver; import io.smallrye.mutiny.Uni; import io.vertx.ext.web.RoutingContext; @ApplicationScoped public class CustomTenantResolver implements TenantConfigResolver { @Override public Uni<OidcTenantConfig> resolve(RoutingContext context, OidcRequestContext<OidcTenantConfig> requestContext) { String path = context.request().path(); if (path.startsWith("/tenant-a")) { String keycloakUrl = ConfigProvider.getConfig().getValue("keycloak.url", String.class); OidcTenantConfig config = new OidcTenantConfig(); config.setTenantId("tenant-a"); config.setAuthServerUrl(keycloakUrl + "/realms/tenant-a"); config.setClientId("multi-tenant-client"); config.getCredentials().setSecret("secret"); config.setApplicationType(ApplicationType.HYBRID); return Uni.createFrom().item(config); } else { // resolve to default tenant config return Uni.createFrom().nullItem(); } } }
前述の実装では、テナントはリクエストパスから解決されます。テナントを推測できない場合は、デフォルトのテナント設定を使用する必要があることを示す null
が返されます。
tenant-a
アプリケーションタイプは hybrid
です。提供されている場合、HTTP ベアラートークンを受け入れることができます。それ以外の場合は、認証が必要なときに認可コードフローを開始します。