Skip to content

Commit

Permalink
Merge pull request #43590 from snazy/oidc-encapsulate-tenants-maps
Browse files Browse the repository at this point in the history
OIDC: Encapsulate static/dynamic tenants maps in `TenantConfigBean`
  • Loading branch information
sberyozkin authored Sep 30, 2024
2 parents cd64f5b + ac50eb6 commit 351b9f9
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public Uni<OidcTenantConfig> apply(OidcTenantConfig oidcTenantConfig) {
final String tenantId = context.get(OidcUtils.TENANT_ID_ATTRIBUTE);

if (tenantId != null && !isTenantSetByAnnotation(context, tenantId)) {
TenantConfigContext tenantContext = tenantConfigBean.getDynamicTenantsConfig().get(tenantId);
TenantConfigContext tenantContext = tenantConfigBean.getDynamicTenant(tenantId);
if (tenantContext != null) {
return Uni.createFrom().item(tenantContext.getOidcTenantConfig());
}
Expand Down Expand Up @@ -197,7 +197,7 @@ private boolean isTenantSetByAnnotation(RoutingContext context, String tenantId)
}

private TenantConfigContext getStaticTenantContext(String tenantId) {
TenantConfigContext configContext = tenantId != null ? tenantConfigBean.getStaticTenantsConfig().get(tenantId) : null;
var configContext = tenantId != null ? tenantConfigBean.getStaticTenant(tenantId) : null;
if (configContext == null) {
if (tenantId != null && !tenantId.isEmpty()) {
LOG.debugf(
Expand Down Expand Up @@ -261,18 +261,18 @@ private Uni<TenantConfigContext> getDynamicTenantContext(RoutingContext context)
@Override
public Uni<? extends TenantConfigContext> apply(OidcTenantConfig tenantConfig) {
if (tenantConfig != null) {
String tenantId = tenantConfig.getTenantId()
var tenantId = tenantConfig.getTenantId()
.orElseThrow(() -> new OIDCException("Tenant configuration must have tenant id"));
TenantConfigContext tenantContext = tenantConfigBean.getDynamicTenantsConfig().get(tenantId);
var tenantContext = tenantConfigBean.getDynamicTenant(tenantId);
if (tenantContext == null) {
return tenantConfigBean.getTenantConfigContextFactory().apply(tenantConfig);
return tenantConfigBean.createDynamicTenantContext(tenantConfig);
} else {
return Uni.createFrom().item(tenantContext);
}
} else {
final String tenantId = context.get(OidcUtils.TENANT_ID_ATTRIBUTE);
if (tenantId != null && !isTenantSetByAnnotation(context, tenantId)) {
TenantConfigContext tenantContext = tenantConfigBean.getDynamicTenantsConfig().get(tenantId);
TenantConfigContext tenantContext = tenantConfigBean.getDynamicTenant(tenantId);
if (tenantContext != null) {
return Uni.createFrom().item(tenantContext);
}
Expand Down Expand Up @@ -304,14 +304,11 @@ public OidcTenantConfig getResolvedConfig(String sessionTenantId) {
return tenantConfigBean.getDefaultTenant().getOidcTenantConfig();
}

if (tenantConfigBean.getStaticTenantsConfig().containsKey(sessionTenantId)) {
return tenantConfigBean.getStaticTenantsConfig().get(sessionTenantId).getOidcTenantConfig();
var tenant = tenantConfigBean.getStaticTenant(sessionTenantId);
if (tenant == null) {
tenant = tenantConfigBean.getDynamicTenant(sessionTenantId);
}

if (tenantConfigBean.getDynamicTenantsConfig().containsKey(sessionTenantId)) {
return tenantConfigBean.getDynamicTenantsConfig().get(sessionTenantId).getOidcTenantConfig();
}
return null;
return tenant != null ? tenant.getOidcTenantConfig() : null;
}

public String getRootPath() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ public class OidcRecorder {
private static final Logger LOG = Logger.getLogger(OidcRecorder.class);
private static final String SECURITY_EVENTS_ENABLED_CONFIG_KEY = "quarkus.security.events.enabled";

private static final Map<String, TenantConfigContext> dynamicTenantsConfig = new ConcurrentHashMap<>();
private static final Set<String> tenantsExpectingServerAvailableEvents = ConcurrentHashMap.newKeySet();
private static volatile boolean userInfoInjectionPointDetected = false;

Expand Down Expand Up @@ -128,42 +127,30 @@ public TenantConfigBean setup(OidcConfig config, Vertx vertxValue, OidcTlsSuppor
staticTenantInitializer));
}

return new TenantConfigBean(staticTenantsConfig, dynamicTenantsConfig, defaultTenantContext,
new Function<OidcTenantConfig, Uni<TenantConfigContext>>() {
return new TenantConfigBean(staticTenantsConfig, defaultTenantContext,
new TenantConfigBean.TenantContextFactory() {
@Override
public Uni<TenantConfigContext> apply(OidcTenantConfig config) {
return createDynamicTenantContext(vertxValue, config, config.getTenantId().get(),
tlsSupport);
public Uni<TenantConfigContext> create(OidcTenantConfig config) {
return createDynamicTenantContext(vertxValue, config, tlsSupport);
}
});
}

private Uni<TenantConfigContext> createDynamicTenantContext(Vertx vertx,
OidcTenantConfig oidcConfig, String tenantId, OidcTlsSupport tlsSupport) {
OidcTenantConfig oidcConfig, OidcTlsSupport tlsSupport) {

var tenantId = oidcConfig.tenantId.orElseThrow();
if (oidcConfig.logout.backchannel.path.isPresent()) {
throw new ConfigurationException(
"BackChannel Logout is currently not supported for dynamic tenants");
}
if (!dynamicTenantsConfig.containsKey(tenantId)) {
Uni<TenantConfigContext> uniContext = createTenantContext(vertx, oidcConfig, false, tenantId, tlsSupport)
.onFailure().transform(new Function<Throwable, Throwable>() {
@Override
public Throwable apply(Throwable t) {
return logTenantConfigContextFailure(t, tenantId);
}
});
return uniContext.onItem().transform(
new Function<TenantConfigContext, TenantConfigContext>() {
@Override
public TenantConfigContext apply(TenantConfigContext t) {
dynamicTenantsConfig.putIfAbsent(tenantId, t);
return t;
}
});
} else {
return Uni.createFrom().item(dynamicTenantsConfig.get(tenantId));
}
return createTenantContext(vertx, oidcConfig, false, tenantId, tlsSupport)
.onFailure().transform(new Function<Throwable, Throwable>() {
@Override
public Throwable apply(Throwable t) {
return logTenantConfigContextFailure(t, tenantId);
}
});
}

private TenantConfigContext createStaticTenantContext(Vertx vertx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public String resolve(RoutingContext context) {
String[] pathSegments = context.request().path().split("/");
if (pathSegments.length > 0) {
String lastPathSegment = pathSegments[pathSegments.length - 1];
if (tenantConfigBean.getStaticTenantsConfig().containsKey(lastPathSegment)) {
if (tenantConfigBean.getStaticTenant(lastPathSegment) != null) {
LOG.debugf(
"Tenant id '%s' is selected on the '%s' request path", lastPathSegment, context.normalizedPath());
return lastPathSegment;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.oidc.runtime;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import jakarta.enterprise.context.spi.CreationalContext;
Expand All @@ -14,33 +15,55 @@ public class TenantConfigBean {
private final Map<String, TenantConfigContext> staticTenantsConfig;
private final Map<String, TenantConfigContext> dynamicTenantsConfig;
private final TenantConfigContext defaultTenant;
private final Function<OidcTenantConfig, Uni<TenantConfigContext>> tenantConfigContextFactory;
private final TenantContextFactory tenantContextFactory;

@FunctionalInterface
public interface TenantContextFactory {
Uni<TenantConfigContext> create(OidcTenantConfig oidcTenantConfig);
}

public TenantConfigBean(
Map<String, TenantConfigContext> staticTenantsConfig,
Map<String, TenantConfigContext> dynamicTenantsConfig,
TenantConfigContext defaultTenant,
Function<OidcTenantConfig, Uni<TenantConfigContext>> tenantConfigContextFactory) {
TenantContextFactory tenantContextFactory) {
this.staticTenantsConfig = Map.copyOf(staticTenantsConfig);
this.dynamicTenantsConfig = dynamicTenantsConfig;
this.dynamicTenantsConfig = new ConcurrentHashMap<>();
this.defaultTenant = defaultTenant;
this.tenantConfigContextFactory = tenantConfigContextFactory;
this.tenantContextFactory = tenantContextFactory;
}

public Uni<TenantConfigContext> createDynamicTenantContext(OidcTenantConfig oidcConfig) {
var tenantId = oidcConfig.tenantId.orElseThrow();

var tenant = dynamicTenantsConfig.get(tenantId);
if (tenant != null) {
return Uni.createFrom().item(tenant);
}

return tenantContextFactory.create(oidcConfig).onItem().transform(
new Function<TenantConfigContext, TenantConfigContext>() {
@Override
public TenantConfigContext apply(TenantConfigContext t) {
dynamicTenantsConfig.putIfAbsent(tenantId, t);
return t;
}
});
}

public Map<String, TenantConfigContext> getStaticTenantsConfig() {
return staticTenantsConfig;
}

public TenantConfigContext getDefaultTenant() {
return defaultTenant;
public TenantConfigContext getStaticTenant(String tenantId) {
return staticTenantsConfig.get(tenantId);
}

public Function<OidcTenantConfig, Uni<TenantConfigContext>> getTenantConfigContextFactory() {
return tenantConfigContextFactory;
public TenantConfigContext getDefaultTenant() {
return defaultTenant;
}

public Map<String, TenantConfigContext> getDynamicTenantsConfig() {
return dynamicTenantsConfig;
public TenantConfigContext getDynamicTenant(String tenantId) {
return dynamicTenantsConfig.get(tenantId);
}

public static class Destroyer implements BeanDestroyer<TenantConfigBean> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public String principalNameMulti2() {
}

private String getClientName() {
OidcTenantConfig oidcConfig = tenantConfigBean.getDynamicTenantsConfig().get(session.getTenantId())
OidcTenantConfig oidcConfig = tenantConfigBean.getDynamicTenant(session.getTenantId())
.getOidcTenantConfig();
return oidcConfig.getClientName().get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public String sessionExpired(@CookieParam("session_expired") String sessionExpir
// Cookie format: jwt|<tenant id>

String[] pair = sessionExpired.split("\\|");
OidcTenantConfig oidcConfig = tenantConfig.getStaticTenantsConfig().get(pair[1]).getOidcTenantConfig();
OidcTenantConfig oidcConfig = tenantConfig.getStaticTenant(pair[1]).getOidcTenantConfig();
JsonWebToken jwt = new DefaultJWTParser().decrypt(pair[0], oidcConfig.credentials.secret.get());

OidcUtils.removeCookie(context, oidcConfig, "session_expired");
Expand Down

0 comments on commit 351b9f9

Please sign in to comment.