Skip to content

Commit

Permalink
Enabling Basic Auth configured at runtime (#155)
Browse files Browse the repository at this point in the history
* Enabling Basic Auth configured at runtime

* more WIP

* finalizing

* remove outdated comment

---------

Co-authored-by: Andrea Peruffo <aperuffo@aperuffo-thinkpadp1gen4i.remote.csb>
  • Loading branch information
andreaTP and Andrea Peruffo committed May 8, 2024
1 parent 0928593 commit 2fea766
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 19 deletions.
5 changes: 5 additions & 0 deletions auth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
<artifactId>quarkus-oidc</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-elytron-security-properties-file</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-fault-tolerance</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Supplier;

import io.quarkus.arc.Unremovable;
import io.quarkus.vertx.http.runtime.security.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.faulttolerance.Retry;
Expand All @@ -52,11 +50,6 @@
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.request.AuthenticationRequest;
import io.quarkus.security.identity.request.TokenAuthenticationRequest;
import io.quarkus.vertx.http.runtime.security.ChallengeData;
import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism;
import io.quarkus.vertx.http.runtime.security.HttpCredentialTransport;
import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
import io.smallrye.jwt.auth.principal.DefaultJWTParser;
import io.smallrye.jwt.auth.principal.ParseException;
import io.smallrye.mutiny.Uni;
Expand All @@ -71,16 +64,22 @@
@Alternative
@Priority(1)
@ApplicationScoped
@Unremovable
public class AppAuthenticationMechanism implements HttpAuthenticationMechanism {

@ConfigProperty(name = "quarkus.oidc.tenant-enabled", defaultValue = "false")
@Info(category = "auth", description = "Enable auth", availableSince = "0.1.18-SNAPSHOT", registryAvailableSince = "2.0.0.Final", studioAvailableSince = "1.0.0")
boolean authEnabled;
boolean oidcAuthEnabled;

// back to fake auth and use another property
@Dynamic(label = "HTTP basic authentication", description = "When selected, users are permitted to authenticate using HTTP basic authentication (in addition to OAuth).", requires = "apicurio.authn.enabled=true")
@ConfigProperty(name = "apicurio.authn.basic-client-credentials.enabled", defaultValue = "false")
@Info(category = "auth", description = "Enable basic auth client credentials", availableSince = "0.1.18-SNAPSHOT", registryAvailableSince = "2.1.0.Final", studioAvailableSince = "1.0.0")
Supplier<Boolean> fakeBasicAuthEnabled;
Supplier<Boolean> basicClientCredentialsAuthEnabled;

@ConfigProperty(name = "quarkus.http.auth.basic", defaultValue = "false")
@Info(category = "auth", description = "Enable basic auth", availableSince = "1.1.X-SNAPSHOT", registryAvailableSince = "3.X.X.Final", studioAvailableSince = "1.0.0")
boolean basicAuthEnabled;

@ConfigProperty(name = "apicurio.authn.basic-client-credentials.cache-expiration", defaultValue = "10")
@Info(category = "auth", description = "Default client credentials token expiration time.", availableSince = "0.1.18-SNAPSHOT", registryAvailableSince = "2.2.6.Final", studioAvailableSince = "1.0.0")
Expand Down Expand Up @@ -111,6 +110,9 @@ public class AppAuthenticationMechanism implements HttpAuthenticationMechanism {
@Info(category = "auth", description = "Client identifier used by the server for authentication.", availableSince = "0.1.18-SNAPSHOT", registryAvailableSince = "2.0.0.Final", studioAvailableSince = "1.0.0")
String clientId;

@Inject
BasicAuthenticationMechanism basicAuthenticationMechanism;

@Inject
OidcAuthenticationMechanism oidcAuthenticationMechanism;

Expand All @@ -133,18 +135,30 @@ public class AppAuthenticationMechanism implements HttpAuthenticationMechanism {

@PostConstruct
public void init() {
if (authEnabled) {
if (oidcAuthEnabled) {
cachedAccessTokens = new ConcurrentHashMap<>();
cachedAuthFailures = new ConcurrentHashMap<>();
httpClient = new VertxHttpClientProvider(vertx).create(authServerUrl, Collections.emptyMap(), null, new AuthErrorHandler());
}
}

private HttpAuthenticationMechanism selectEnabledAuth() {
if (basicAuthEnabled) {
return basicAuthenticationMechanism;
} else if (oidcAuthEnabled) {
return oidcAuthenticationMechanism;
} else {
return null;
}
}

@Override
public Uni<SecurityIdentity> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) {
if (authEnabled) {
if (basicAuthEnabled) {
return basicAuthenticationMechanism.authenticate(context, identityProviderManager);
} else if (oidcAuthEnabled) {
setAuditLogger(context);
if (fakeBasicAuthEnabled.get()) {
if (basicClientCredentialsAuthEnabled.get()) {
final Pair<String, String> clientCredentials = CredentialsHelper.extractCredentialsFromContext(context);
if (null != clientCredentials) {
try {
Expand Down Expand Up @@ -222,17 +236,30 @@ public String getForwardedFor() {

@Override
public Uni<ChallengeData> getChallenge(RoutingContext context) {
return oidcAuthenticationMechanism.getChallenge(context);
var enabledAuth = selectEnabledAuth();
if (enabledAuth != null) {
return enabledAuth.getChallenge(context);
} else {
return Uni.createFrom().nullItem();
}
}

@Override
public Set<Class<? extends AuthenticationRequest>> getCredentialTypes() {
return Collections.singleton(TokenAuthenticationRequest.class);
Set<Class<? extends AuthenticationRequest>> credentialTypes = new HashSet<>();
credentialTypes.addAll(oidcAuthenticationMechanism.getCredentialTypes());
credentialTypes.addAll(basicAuthenticationMechanism.getCredentialTypes());
return credentialTypes;
}

@Override
public HttpCredentialTransport getCredentialTransport() {
return new HttpCredentialTransport(HttpCredentialTransport.Type.AUTHORIZATION, "bearer");
public Uni<HttpCredentialTransport> getCredentialTransport(RoutingContext context) {
var enabledAuth = selectEnabledAuth();
if (enabledAuth != null) {
return enabledAuth.getCredentialTransport(context);
} else {
return Uni.createFrom().nullItem();
}
}

private Uni<SecurityIdentity> authenticateWithClientCredentials(Pair<String, String> clientCredentials, RoutingContext context, IdentityProviderManager identityProviderManager) {
Expand Down

0 comments on commit 2fea766

Please sign in to comment.