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