package io.quarkus.it.keycloak;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.function.Supplier;
import io.smallrye.mutiny.Uni;
import io.quarkus.oidc.OidcRequestContext;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.TenantConfigResolver;
import io.vertx.ext.web.RoutingContext;
@ApplicationScoped
public class CustomTenantConfigResolver implements TenantConfigResolver {
@Override
public Uni<OidcTenantConfig> resolve(RoutingContext context, OidcRequestContext<OidcTenantConfig> requestContext) {
String path = context.request().path();
String[] parts = path.split("/");
if (parts.length == 0) {
//Resolve to default tenant configuration
return null;
}
if ("tenant-c".equals(parts[1])) {
// Do 'return requestContext.runBlocking(createTenantConfig());'
// if a blocking call is required to create a tenant config,
return Uni.createFromItem(createTenantConfig());
}
//Resolve to default tenant configuration
return null;
}
private Supplier<OidcTenantConfig> createTenantConfig() {
final OidcTenantConfig config = new OidcTenantConfig();
config.setTenantId("tenant-c");
config.setAuthServerUrl("http://localhost:8180/realms/tenant-c");
config.setClientId("multi-tenant-client");
OidcTenantConfig.Credentials credentials = new OidcTenantConfig.Credentials();
credentials.setSecret("my-secret");
config.setCredentials(credentials);
// Any other setting supported by the quarkus-oidc extension
return () -> config;
}
}
package io.quarkus.it.keycloak;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.function.Supplier;
import io.smallrye.mutiny.Uni;
import io.quarkus.oidc.OidcRequestContext;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.TenantConfigResolver;
import io.vertx.ext.web.RoutingContext;
@ApplicationScoped
public class CustomTenantConfigResolver implements TenantConfigResolver {
@Override
public Uni<OidcTenantConfig> resolve(RoutingContext context, OidcRequestContext<OidcTenantConfig> requestContext) {
String path = context.request().path();
String[] parts = path.split("/");
if (parts.length == 0) {
//Resolve to default tenant configuration
return null;
}
if ("tenant-c".equals(parts[1])) {
// Do 'return requestContext.runBlocking(createTenantConfig());'
// if a blocking call is required to create a tenant config,
return Uni.createFromItem(createTenantConfig());
}
//Resolve to default tenant configuration
return null;
}
private Supplier<OidcTenantConfig> createTenantConfig() {
final OidcTenantConfig config = new OidcTenantConfig();
config.setTenantId("tenant-c");
config.setAuthServerUrl("http://localhost:8180/realms/tenant-c");
config.setClientId("multi-tenant-client");
OidcTenantConfig.Credentials credentials = new OidcTenantConfig.Credentials();
credentials.setSecret("my-secret");
config.setCredentials(credentials);
// Any other setting supported by the quarkus-oidc extension
return () -> config;
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
解析 OIDC web-app
应用程序配置的最简单选项是按照 Default resolution 部分中描述的步骤进行操作。
如果默认解析策略不适用于应用程序设置,请尝试以下其中一个选项。
有几个选项可用于选择租户配置,这些配置应该用来保护 服务和
web-app
OIDC 应用程序的当前 HTTP 请求,例如:
-
检查 URL 路径。例如,
tenant-service
配置必须用于 /service
路径,而 tenant-manage
配置必须用于 /management
路径。
-
检查 HTTP 标头。例如,如果 URL 路径始终为
/service
,一个标头(如 Realm: service
或 Realm: 管理
)可帮助选择 tenant-service
和 tenant-manage
配置。
-
检查 URL 查询参数。它的工作方式与标头用于选择租户配置的方式类似。
所有这些选项都可以使用 OIDC 服务
应用程序的 custom TenantResolver
和 TenantConfigResolver
实现轻松实现。
但是,由于 HTTP 重定向需要完成 OIDC web-app
应用程序的代码身份验证流,可能需要自定义 HTTP cookie 以在此重定向请求前后选择相同的租户配置,因为:
-
如果在 OIDC 供应商中注册了单个重定向 URL,在重定向请求后 URL 路径可能不同。在租户配置解决后,可以恢复原始请求路径。
-
重定向后,原始请求中使用的 HTTP 标头不可用。
-
自定义 URL 查询参数在重定向后恢复,但仅在租户配置解决后恢复。
其中一个选项是确保解析 web-app
应用程序的租户配置的信息在重定向之前和之后可用,例如:
package org.acme.quickstart.oidc;
import java.util.List;
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.oidc.TenantResolver;
import io.vertx.core.http.Cookie;
import io.vertx.ext.web.RoutingContext;
@ApplicationScoped
public class CustomTenantResolver implements TenantResolver {
@Override
public String resolve(RoutingContext context) {
List<String> tenantIdQuery = context.queryParam("tenantId");
if (!tenantIdQuery.isEmpty()) {
String tenantId = tenantIdQuery.get(0);
context.response().addCookie(Cookie.cookie("tenant", tenantId));
return tenantId;
} else if (!context.request().cookies("tenant").isEmpty()) {
return context.request().getCookie("tenant").getValue();
}
return null;
}
}
package org.acme.quickstart.oidc;
import java.util.List;
import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.oidc.TenantResolver;
import io.vertx.core.http.Cookie;
import io.vertx.ext.web.RoutingContext;
@ApplicationScoped
public class CustomTenantResolver implements TenantResolver {
@Override
public String resolve(RoutingContext context) {
List<String> tenantIdQuery = context.queryParam("tenantId");
if (!tenantIdQuery.isEmpty()) {
String tenantId = tenantIdQuery.get(0);
context.response().addCookie(Cookie.cookie("tenant", tenantId));
return tenantId;
} else if (!context.request().cookies("tenant").isEmpty()) {
return context.request().getCookie("tenant").getValue();
}
return null;
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow