Skip to content

Commit

Permalink
Merge pull request quarkusio#43433 from michalvavrik/feature/fix-oidc…
Browse files Browse the repository at this point in the history
…-issuer-unavailable

Make sure OIDC issuer-based tenant resolver can recover when OIDC server becomes available after Quarkus app started
  • Loading branch information
sberyozkin authored Sep 24, 2024
2 parents cb31fbb + f2a2955 commit 2dc0028
Show file tree
Hide file tree
Showing 18 changed files with 1,000 additions and 610 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ quarkus.oidc.application-type=web-app
quarkus.oidc.logout.path=/protected/logout
quarkus.oidc.authentication.pkce-required=true
quarkus.log.category."org.htmlunit".level=ERROR
quarkus.log.category."io.quarkus.oidc.runtime.TenantConfigContext".level=DEBUG
quarkus.log.category."io.quarkus.oidc.runtime.TenantConfigContextImpl".level=DEBUG
quarkus.log.file.enable=true

# use blocking DNS lookup so that we have it tested somewhere
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void accept(MultiMap form) {
try {
// Do the general validation of the logout token now, compare with the IDToken later
// Check the signature, as well the issuer and audience if it is configured
TokenVerificationResult result = tenantContext.provider
TokenVerificationResult result = tenantContext.provider()
.verifyLogoutJwtToken(encodedLogoutToken);

if (verifyLogoutTokenClaims(result)) {
Expand Down Expand Up @@ -162,9 +162,9 @@ private TenantConfigContext getTenantConfigContext(final String requestPath) {
}

private boolean isMatchingTenant(String requestPath, TenantConfigContext tenant) {
return tenant.oidcConfig.isTenantEnabled()
&& tenant.oidcConfig.getTenantId().get().equals(oidcTenantConfig.getTenantId().get())
&& requestPath.equals(getRootPath() + tenant.oidcConfig.logout.backchannel.path.orElse(null));
return tenant.oidcConfig().isTenantEnabled()
&& tenant.oidcConfig().getTenantId().get().equals(oidcTenantConfig.getTenantId().get())
&& requestPath.equals(getRootPath() + tenant.oidcConfig().logout.backchannel.path.orElse(null));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public Uni<ChallengeData> getChallenge(RoutingContext context) {
@Override
public Uni<ChallengeData> apply(TenantConfigContext tenantContext) {
return Uni.createFrom().item(new ChallengeData(HttpResponseStatus.UNAUTHORIZED.code(),
HttpHeaderNames.WWW_AUTHENTICATE, tenantContext.oidcConfig.token.authorizationScheme));
HttpHeaderNames.WWW_AUTHENTICATE, tenantContext.oidcConfig().token.authorizationScheme));
}
});
}
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package io.quarkus.oidc.runtime;

import java.util.List;
import java.util.function.Supplier;

import javax.crypto.SecretKey;

import org.jboss.logging.Logger;

import io.quarkus.oidc.OidcConfigurationMetadata;
import io.quarkus.oidc.OidcRedirectFilter;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.Redirect;
import io.smallrye.mutiny.Uni;

final class LazyTenantConfigContext implements TenantConfigContext {

private static final Logger LOG = Logger.getLogger(LazyTenantConfigContext.class);

private final Supplier<Uni<TenantConfigContext>> staticTenantCreator;
private volatile TenantConfigContext delegate;

LazyTenantConfigContext(TenantConfigContext delegate, Supplier<Uni<TenantConfigContext>> staticTenantCreator) {
this.staticTenantCreator = staticTenantCreator;
this.delegate = delegate;
}

@Override
public Uni<TenantConfigContext> initialize() {
if (!delegate.ready()) {
LOG.debugf("Tenant '%s' is not initialized yet, trying to create OIDC connection now",
delegate.oidcConfig().tenantId.get());
return staticTenantCreator.get().invoke(ctx -> LazyTenantConfigContext.this.delegate = ctx);
}
return Uni.createFrom().item(delegate);
}

@Override
public OidcTenantConfig oidcConfig() {
return delegate.oidcConfig();
}

@Override
public OidcProvider provider() {
return delegate.provider();
}

@Override
public boolean ready() {
return delegate.ready();
}

@Override
public OidcTenantConfig getOidcTenantConfig() {
return delegate.getOidcTenantConfig();
}

@Override
public OidcConfigurationMetadata getOidcMetadata() {
return delegate.getOidcMetadata();
}

@Override
public OidcProviderClient getOidcProviderClient() {
return delegate.getOidcProviderClient();
}

@Override
public SecretKey getStateEncryptionKey() {
return delegate.getStateEncryptionKey();
}

@Override
public SecretKey getTokenEncSecretKey() {
return delegate.getTokenEncSecretKey();
}

@Override
public SecretKey getInternalIdTokenSecretKey() {
return delegate.getInternalIdTokenSecretKey();
}

@Override
public List<OidcRedirectFilter> getOidcRedirectFilters(Redirect.Location loc) {
return delegate.getOidcRedirectFilters(loc);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public class OidcConfigurationMetadataProducer {
OidcConfigurationMetadata produce() {
OidcConfigurationMetadata configMetadata = OidcUtils.getAttribute(identity, OidcUtils.CONFIG_METADATA_ATTRIBUTE);

if (configMetadata == null && tenantConfig.getDefaultTenant().oidcConfig.tenantEnabled) {
configMetadata = tenantConfig.getDefaultTenant().provider.getMetadata();
if (configMetadata == null && tenantConfig.getDefaultTenant().oidcConfig().tenantEnabled) {
configMetadata = tenantConfig.getDefaultTenant().provider().getMetadata();
}
if (configMetadata == null) {
throw new OIDCException("OidcConfigurationMetadata can not be injected");
Expand Down
Loading

0 comments on commit 2dc0028

Please sign in to comment.