Skip to content

Commit

Permalink
Merge pull request quarkusio#44697 from michalvavrik/feature/add-oidc…
Browse files Browse the repository at this point in the history
…-client-config-builder

Add OIDC Client config builder
  • Loading branch information
sberyozkin authored Nov 28, 2024
2 parents cffea0c + 5a51c3a commit d4cbdb2
Show file tree
Hide file tree
Showing 31 changed files with 2,489 additions and 185 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,8 @@ import java.util.Map;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.OidcClientConfig;
import io.quarkus.oidc.client.OidcClientConfig.Grant.Type;
import io.quarkus.oidc.client.runtime.OidcClientConfig;
import io.quarkus.oidc.client.runtime.OidcClientConfig.Grant.Type;
import io.quarkus.oidc.client.OidcClients;
import io.quarkus.runtime.StartupEvent;
import io.smallrye.mutiny.Uni;
Expand All @@ -383,14 +383,14 @@ public class OidcClientCreator {
}
private Uni<OidcClient> createOidcClient() {
OidcClientConfig cfg = new OidcClientConfig();
cfg.setId("myclient");
cfg.setAuthServerUrl(oidcProviderAddress);
cfg.setClientId("backend-service");
cfg.getCredentials().setSecret("secret");
cfg.getGrant().setType(Type.PASSWORD);
cfg.setGrantOptions(Map.of("password",
Map.of("username", "alice", "password", "alice")));
OidcClientConfig cfg = OidcClientConfig
.authServerUrl(oidcProviderAddress)
.id("myclient")
.clientId("backend-service")
.credentials("secret")
.grant(Type.PASSWORD)
.grantOptions("password", Map.of("username", "alice", "password", "alice"))
.build();
return oidcClients.newClient(cfg);
}
}
Expand Down
16 changes: 8 additions & 8 deletions docs/src/main/asciidoc/security-openid-connect-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -303,14 +303,14 @@ public class OidcClientCreator {
}
private Uni<OidcClient> createOidcClient() {
OidcClientConfig cfg = new OidcClientConfig();
cfg.setId("myclient");
cfg.setAuthServerUrl(oidcProviderAddress);
cfg.setClientId("backend-service");
cfg.getCredentials().setSecret("secret");
cfg.getGrant().setType(Type.PASSWORD);
cfg.setGrantOptions(Map.of("password",
Map.of("username", "alice", "password", "alice")));
OidcClientConfig cfg = OidcClientConfig
.authServerUrl(oidcProviderAddress)
.id("myclient")
.clientId("backend-service")
.credentials("secret")
.grant(Type.PASSWORD)
.grantOptions("password", Map.of("username", "alice", "password", "alice"))
.build();
return oidcClients.newClient(cfg);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class DefaultPolicyEnforcerResolver implements PolicyEnforcerResolver {
}

var defaultTenantConfig = new OidcTenantConfig(OidcConfig.getDefaultTenant(oidcConfig), OidcUtils.DEFAULT_TENANT_ID);
var defaultTenantTlsSupport = tlsSupport.forConfig(defaultTenantConfig.tls);
var defaultTenantTlsSupport = tlsSupport.forConfig(defaultTenantConfig.tls());
this.defaultPolicyEnforcer = createPolicyEnforcer(defaultTenantConfig, config.defaultTenant(),
defaultTenantTlsSupport);
this.namedPolicyEnforcers = createNamedPolicyEnforcers(oidcConfig, config, tlsSupport);
Expand Down Expand Up @@ -101,7 +101,7 @@ private Uni<PolicyEnforcer> getDynamicPolicyEnforcer(RoutingContext routingConte
.onItem().ifNotNull().transform(new Function<KeycloakPolicyEnforcerTenantConfig, PolicyEnforcer>() {
@Override
public PolicyEnforcer apply(KeycloakPolicyEnforcerTenantConfig tenant) {
return createPolicyEnforcer(config, tenant, tlsSupport.forConfig(config.tls));
return createPolicyEnforcer(config, tenant, tlsSupport.forConfig(config.tls()));
}
});
}
Expand All @@ -116,7 +116,7 @@ private static Map<String, PolicyEnforcer> createNamedPolicyEnforcers(OidcConfig
for (Map.Entry<String, KeycloakPolicyEnforcerTenantConfig> tenant : config.namedTenants().entrySet()) {
OidcTenantConfig oidcTenantConfig = getOidcTenantConfig(oidcConfig, tenant.getKey());
policyEnforcerTenants.put(tenant.getKey(),
createPolicyEnforcer(oidcTenantConfig, tenant.getValue(), tlsSupport.forConfig(oidcTenantConfig.tls)));
createPolicyEnforcer(oidcTenantConfig, tenant.getValue(), tlsSupport.forConfig(oidcTenantConfig.tls())));
}
return Map.copyOf(policyEnforcerTenants);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

import io.quarkus.oidc.OIDCException;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.common.runtime.OidcCommonConfig;
import io.quarkus.oidc.common.runtime.OidcTlsSupport.TlsConfigSupport;
import io.quarkus.oidc.common.runtime.config.OidcCommonConfig;
import io.quarkus.oidc.runtime.OidcConfig;
import io.quarkus.runtime.configuration.ConfigurationException;

Expand Down Expand Up @@ -53,16 +53,16 @@ static PolicyEnforcer createPolicyEnforcer(OidcTenantConfig oidcConfig,
adapterConfig.setCredentials(getCredentials(oidcConfig));

if (!tlsConfigSupport.useTlsRegistry()) {
boolean trustAll = oidcConfig.tls.getVerification().isPresent()
? oidcConfig.tls.getVerification().get() == OidcCommonConfig.Tls.Verification.NONE
boolean trustAll = oidcConfig.tls().verification().isPresent()
? oidcConfig.tls().verification().get() == OidcCommonConfig.Tls.Verification.NONE
: tlsConfigSupport.isGlobalTrustAll();
if (trustAll) {
adapterConfig.setDisableTrustManager(true);
adapterConfig.setAllowAnyHostname(true);
} else if (oidcConfig.tls.trustStoreFile.isPresent()) {
adapterConfig.setTruststore(oidcConfig.tls.trustStoreFile.get().toString());
adapterConfig.setTruststorePassword(oidcConfig.tls.trustStorePassword.orElse("password"));
if (OidcCommonConfig.Tls.Verification.CERTIFICATE_VALIDATION == oidcConfig.tls.verification
} else if (oidcConfig.tls().trustStoreFile().isPresent()) {
adapterConfig.setTruststore(oidcConfig.tls().trustStoreFile().get().toString());
adapterConfig.setTruststorePassword(oidcConfig.tls().trustStorePassword().orElse("password"));
if (OidcCommonConfig.Tls.Verification.CERTIFICATE_VALIDATION == oidcConfig.tls().verification()
.orElse(OidcCommonConfig.Tls.Verification.REQUIRED)) {
adapterConfig.setAllowAnyHostname(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
import io.quarkus.gizmo.ClassCreator;
import io.quarkus.gizmo.ClassOutput;
Expand All @@ -46,6 +47,7 @@
import io.quarkus.oidc.client.Tokens;
import io.quarkus.oidc.client.runtime.AbstractTokensProducer;
import io.quarkus.oidc.client.runtime.OidcClientBuildTimeConfig;
import io.quarkus.oidc.client.runtime.OidcClientDefaultIdConfigBuilder;
import io.quarkus.oidc.client.runtime.OidcClientRecorder;
import io.quarkus.oidc.client.runtime.OidcClientsConfig;
import io.quarkus.oidc.client.runtime.TokenProviderProducer;
Expand Down Expand Up @@ -184,6 +186,11 @@ private AccessTokenInstanceBuildItem build() {
return index.getIndex().getAnnotations(ACCESS_TOKEN).stream().map(ItemBuilder::new).map(ItemBuilder::build).toList();
}

@BuildStep
RunTimeConfigBuilderBuildItem useOidcClientDefaultIdConfigBuilder() {
return new RunTimeConfigBuilderBuildItem(OidcClientDefaultIdConfigBuilder.class);
}

/**
* Creates a Tokens producer class like follows:
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.oidc.client.runtime.OidcClientsConfig;
import io.quarkus.oidc.runtime.OidcUtils;
import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;
Expand All @@ -25,6 +29,23 @@ public class OidcClientKeycloakDevServiceTest {
.addClasses(NamedOidcClientResource.class)
.addAsResource("oidc-client-dev-service-test.properties", "application.properties"));

@Inject
OidcClientsConfig config;

@Test
public void testOidcClientDefaultIdIsSet() {
var defaultClientConfig = OidcClientsConfig.getDefaultClient(config);
// not set, so "Default" id should be set by Quarkus
assertEquals("Default", defaultClientConfig.id().orElse(null));
// not set, so named key "client1" should be set by Quarkus
assertEquals("client1", config.namedClients().get("client1").id().orElse(null));
// set to "client2" in application.properties
// we cannot set here any different value, because ATM OIDC client enforce that ID always equal named key anyway
assertEquals("client2", config.namedClients().get("client2").id().orElse(null));
// not set and named key "client3" is enclosed in double quotes, so named key "client3" should be set by Quarkus
assertEquals("client3", config.namedClients().get("client3").id().orElse(null));
}

@Test
public void testInjectedNamedOidcClients() {
String token1 = doTestGetTokenByNamedClient("client1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,11 @@ quarkus.oidc-client.client2.credentials.secret=${quarkus.oidc-client.credentials
quarkus.oidc-client.client2.grant.type=password
quarkus.oidc-client.client2.grant-options.password.username=bob
quarkus.oidc-client.client2.grant-options.password.password=bob
quarkus.oidc-client.client2.id=client2

quarkus.oidc-client."client3".auth-server-url=${quarkus.oidc-client.auth-server-url}
quarkus.oidc-client."client3".client-id=${quarkus.oidc-client.client-id}
quarkus.oidc-client."client3".credentials.secret=${quarkus.oidc-client.credentials.secret}
quarkus.oidc-client."client3".grant.type=password
quarkus.oidc-client."client3".grant-options.password.username=bob
quarkus.oidc-client."client3".grant-options.password.password=bob
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
import io.quarkus.oidc.common.runtime.OidcClientCommonConfig;
import io.quarkus.oidc.common.runtime.OidcConstants;

public class OidcClientConfig extends OidcClientCommonConfig {
/**
* @deprecated create {@link io.quarkus.oidc.client.runtime.OidcClientConfig} with the {@link OidcClientConfigBuilder}
* for example, you can use the {@link io.quarkus.oidc.client.runtime.OidcClientConfig#builder()} method.
*/
@Deprecated(since = "3.18")
public class OidcClientConfig extends OidcClientCommonConfig implements io.quarkus.oidc.client.runtime.OidcClientConfig {

public OidcClientConfig() {

Expand Down Expand Up @@ -67,7 +72,82 @@ public OidcClientConfig(io.quarkus.oidc.client.runtime.OidcClientConfig mapping)

public Grant grant = new Grant();

public static class Grant {
@Override
public Optional<String> id() {
return id;
}

@Override
public boolean clientEnabled() {
return clientEnabled;
}

@Override
public Optional<List<String>> scopes() {
return scopes;
}

@Override
public Optional<Duration> refreshTokenTimeSkew() {
return refreshTokenTimeSkew;
}

@Override
public Optional<Duration> accessTokenExpiresIn() {
return accessTokenExpiresIn;
}

@Override
public boolean absoluteExpiresIn() {
return absoluteExpiresIn;
}

@Override
public io.quarkus.oidc.client.runtime.OidcClientConfig.Grant grant() {
return grant;
}

@Override
public Map<String, Map<String, String>> grantOptions() {
return grantOptions;
}

@Override
public boolean earlyTokensAcquisition() {
return earlyTokensAcquisition;
}

@Override
public Map<String, String> headers() {
return headers;
}

public static class Grant implements io.quarkus.oidc.client.runtime.OidcClientConfig.Grant {

@Override
public io.quarkus.oidc.client.runtime.OidcClientConfig.Grant.Type type() {
return type == null ? null : io.quarkus.oidc.client.runtime.OidcClientConfig.Grant.Type.valueOf(type.toString());
}

@Override
public String accessTokenProperty() {
return accessTokenProperty;
}

@Override
public String refreshTokenProperty() {
return refreshTokenProperty;
}

@Override
public String expiresInProperty() {
return expiresInProperty;
}

@Override
public String refreshExpiresInProperty() {
return refreshExpiresInProperty;
}

public static enum Type {
/**
Expand Down
Loading

0 comments on commit d4cbdb2

Please sign in to comment.