Skip to content

Commit

Permalink
Fix quarkiverse#940 - Change authorization properties configuration t…
Browse files Browse the repository at this point in the history
…o RUNTIME

Signed-off-by: Ricardo Zanini <[email protected]>
  • Loading branch information
ricardozanini committed Jan 20, 2025
1 parent c311e94 commit b2c7c72
Show file tree
Hide file tree
Showing 18 changed files with 1,069 additions and 190 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,22 @@

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Priority;
import jakarta.inject.Inject;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;

import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
import io.quarkiverse.openapi.generator.SpecItemConfig;
import io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider;
import io.quarkiverse.openapi.generator.providers.ApiKeyIn;
import io.quarkiverse.openapi.generator.providers.AuthProvider;

@Priority(Priorities.AUTHENTICATION)
public class DummyApiKeyAuthenticationProvider implements ClientRequestFilter {

@Inject
OpenApiGeneratorConfig generatorConfig;

private AuthProvider authProvider;

@PostConstruct
public void init() {
authProvider = new ApiKeyAuthenticationProvider("open_weather_custom_security_yaml", "app_id", ApiKeyIn.query, "appid",
generatorConfig.getItemConfig("open_weather_custom_security_yaml")
.flatMap(SpecItemConfig::getAuth).flatMap(x -> x.getItemConfig("app_id")).orElse(null),
List.of());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import java.util.List;
import java.util.function.Function;

import io.quarkiverse.openapi.generator.AuthenticationRecorder;
import io.quarkiverse.openapi.generator.OidcClient;
import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
import io.quarkiverse.openapi.generator.oidc.providers.OAuth2AuthenticationProvider;
import io.quarkiverse.openapi.generator.providers.AuthProvider;
import io.quarkiverse.openapi.generator.providers.OperationAuthInfo;
Expand All @@ -14,18 +12,15 @@

@Recorder
public class OidcAuthenticationRecorder {
private final OpenApiGeneratorConfig generatorConfig;

public OidcAuthenticationRecorder(OpenApiGeneratorConfig generatorConfig) {
this.generatorConfig = generatorConfig;
public OidcAuthenticationRecorder() {
}

public Function<SyntheticCreationalContext<AuthProvider>, AuthProvider> recordOauthAuthProvider(
String name,
String openApiSpecId,
List<OperationAuthInfo> operations) {
return context -> new OAuth2AuthenticationProvider(
AuthenticationRecorder.getAuthConfig(generatorConfig, openApiSpecId, name), name, openApiSpecId,
return context -> new OAuth2AuthenticationProvider(name, openApiSpecId,
context.getInjectedReference(OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate.class,
new OidcClient.Literal(name)),
operations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.quarkiverse.openapi.generator.AuthConfig;
import io.quarkiverse.openapi.generator.providers.AbstractAuthProvider;
import io.quarkiverse.openapi.generator.providers.OperationAuthInfo;
import io.quarkus.oidc.common.runtime.OidcConstants;
Expand All @@ -22,9 +21,9 @@ public class OAuth2AuthenticationProvider extends AbstractAuthProvider {

private final OidcClientRequestFilterDelegate delegate;

public OAuth2AuthenticationProvider(final AuthConfig authConfig, String name,
public OAuth2AuthenticationProvider(String name,
String openApiSpecId, OidcClientRequestFilterDelegate delegate, List<OperationAuthInfo> operations) {
super(authConfig, name, openApiSpecId, operations);
super(name, openApiSpecId, operations);
this.delegate = delegate;
validateConfig();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
public class AuthConfig {

public static final String TOKEN_PROPAGATION = "token-propagation";
public static final String HEADER_NAME = "header-name";

/**
* Enables the authentication token propagation for this particular securityScheme.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.quarkiverse.openapi.generator;

import java.util.List;
import java.util.Objects;
import java.util.function.Function;

import jakarta.enterprise.inject.Instance;
Expand All @@ -21,10 +20,8 @@
@Recorder
public class AuthenticationRecorder {

final OpenApiGeneratorConfig generatorConfig;
public AuthenticationRecorder() {

public AuthenticationRecorder(OpenApiGeneratorConfig generatorConfig) {
this.generatorConfig = generatorConfig;
}

public Function<SyntheticCreationalContext<CompositeAuthenticationProvider>, CompositeAuthenticationProvider> recordCompositeProvider(
Expand All @@ -42,34 +39,22 @@ public Function<SyntheticCreationalContext<AuthProvider>, AuthProvider> recordAp
ApiKeyIn apiKeyIn,
String apiKeyName,
List<OperationAuthInfo> operations) {
return context -> new ApiKeyAuthenticationProvider(openApiSpecId, name, apiKeyIn, apiKeyName,
getAuthConfig(generatorConfig, openApiSpecId, name),
operations);
return context -> new ApiKeyAuthenticationProvider(openApiSpecId, name, apiKeyIn, apiKeyName, operations);
}

public Function<SyntheticCreationalContext<AuthProvider>, AuthProvider> recordBearerAuthProvider(
String name,
String scheme,
String openApiSpecId,
List<OperationAuthInfo> operations) {
return context -> new BearerAuthenticationProvider(openApiSpecId, name, scheme,
getAuthConfig(generatorConfig, openApiSpecId, name),
operations);
return context -> new BearerAuthenticationProvider(openApiSpecId, name, scheme, operations);
}

public Function<SyntheticCreationalContext<AuthProvider>, AuthProvider> recordBasicAuthProvider(
String name,
String openApiSpecId,
List<OperationAuthInfo> operations) {
return context -> new BasicAuthenticationProvider(openApiSpecId, name,
getAuthConfig(generatorConfig, openApiSpecId, name), operations);
return context -> new BasicAuthenticationProvider(openApiSpecId, name, operations);
}

public static AuthConfig getAuthConfig(OpenApiGeneratorConfig generatorConfig, String openApiSpecId, String name) {
return Objects.requireNonNull(generatorConfig, "generatorConfig can't be null.")
.getItemConfig(openApiSpecId)
.flatMap(SpecItemConfig::getAuth)
.flatMap(authsConfig -> authsConfig.getItemConfig(name))
.orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
/**
* This class represents the runtime configurations for the openapi-generator extension.
*/
@ConfigRoot(name = OpenApiGeneratorConfig.RUNTIME_TIME_CONFIG_PREFIX, phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
@ConfigRoot(name = OpenApiGeneratorConfig.RUNTIME_TIME_CONFIG_PREFIX, phase = ConfigPhase.RUN_TIME)
public class OpenApiGeneratorConfig {

public static final String RUNTIME_TIME_CONFIG_PREFIX = "openapi-generator";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MultivaluedMap;

import org.eclipse.microprofile.config.ConfigProvider;

import io.quarkiverse.openapi.generator.AuthConfig;

public abstract class AbstractAuthProvider implements AuthProvider {
Expand All @@ -20,14 +22,12 @@ public abstract class AbstractAuthProvider implements AuthProvider {

private final String openApiSpecId;
private final String name;
private final AuthConfig authConfig;
private final List<OperationAuthInfo> applyToOperations = new ArrayList<>();

protected AbstractAuthProvider(AuthConfig authConfig, String name, String openApiSpecId,
protected AbstractAuthProvider(String name, String openApiSpecId,
List<OperationAuthInfo> operations) {
this.name = name;
this.openApiSpecId = openApiSpecId;
this.authConfig = authConfig;
this.applyToOperations.addAll(operations);
}

Expand All @@ -41,7 +41,8 @@ public String getName() {
}

public boolean isTokenPropagation() {
return authConfig != null && authConfig.getTokenPropagation().orElse(false);
return ConfigProvider.getConfig().getOptionalValue(getCanonicalAuthConfigPropertyName(AuthConfig.TOKEN_PROPAGATION),
Boolean.class).orElse(false);
}

public String getTokenForPropagation(MultivaluedMap<String, Object> httpHeaders) {
Expand All @@ -51,32 +52,23 @@ public String getTokenForPropagation(MultivaluedMap<String, Object> httpHeaders)
}

public String getHeaderName() {
if (authConfig != null) {
return authConfig.getHeaderName().orElse(null);
}
return null;
return ConfigProvider.getConfig()
.getOptionalValue(getCanonicalAuthConfigPropertyName(AuthConfig.HEADER_NAME), String.class).orElse(null);
}

@Override
public List<OperationAuthInfo> operationsToFilter() {
return applyToOperations;
}

public String getAuthConfigParam(String paramName, String defaultValue) {
if (authConfig != null) {
return authConfig.getConfigParam(paramName).orElse(defaultValue);
}
return defaultValue;
}

protected static String sanitizeBearerToken(String token) {
if (token != null && token.toLowerCase().startsWith(BEARER_WITH_SPACE.toLowerCase())) {
return token.substring(BEARER_WITH_SPACE.length());
}
return token;
}

protected String getCanonicalAuthConfigPropertyName(String authPropertyName) {
public final String getCanonicalAuthConfigPropertyName(String authPropertyName) {
return String.format(CANONICAL_AUTH_CONFIG_PROPERTY_NAME, getOpenApiSpecId(), getName(), authPropertyName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.UriBuilder;

import org.eclipse.microprofile.config.ConfigProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.quarkiverse.openapi.generator.AuthConfig;
import io.quarkiverse.openapi.generator.OpenApiGeneratorException;

/**
Expand All @@ -30,9 +30,8 @@ public class ApiKeyAuthenticationProvider extends AbstractAuthProvider {
private final String apiKeyName;

public ApiKeyAuthenticationProvider(final String openApiSpecId, final String name, final ApiKeyIn apiKeyIn,
final String apiKeyName,
final AuthConfig authConfig, List<OperationAuthInfo> operations) {
super(authConfig, name, openApiSpecId, operations);
final String apiKeyName, List<OperationAuthInfo> operations) {
super(name, openApiSpecId, operations);
this.apiKeyIn = apiKeyIn;
this.apiKeyName = apiKeyName;
validateConfig();
Expand All @@ -59,16 +58,19 @@ && isUseAuthorizationHeaderValue()) {
}

private String getApiKey() {
final String key = getAuthConfigParam(API_KEY, "");
final String key = ConfigProvider.getConfig()
.getOptionalValue(getCanonicalAuthConfigPropertyName(API_KEY), String.class).orElse("");
if (key.isEmpty()) {
LOGGER.warn("configured " + API_KEY + " property (see application.properties) is empty. hint: configure it.");
LOGGER.warn("configured {} property (see application.properties) is empty. hint: configure it.",
getCanonicalAuthConfigPropertyName(API_KEY));
}
return key;
}

private boolean isUseAuthorizationHeaderValue() {
final String value = getAuthConfigParam(USE_AUTHORIZATION_HEADER_VALUE, "true");
return "true".equals(value);
return ConfigProvider.getConfig()
.getOptionalValue(getCanonicalAuthConfigPropertyName(USE_AUTHORIZATION_HEADER_VALUE), Boolean.class)
.orElse(true);
}

private void validateConfig() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.core.HttpHeaders;

import io.quarkiverse.openapi.generator.AuthConfig;
import org.eclipse.microprofile.config.ConfigProvider;

import io.quarkiverse.openapi.generator.OpenApiGeneratorException;

/**
Expand All @@ -21,18 +22,19 @@ public class BasicAuthenticationProvider extends AbstractAuthProvider {
static final String USER_NAME = "username";
static final String PASSWORD = "password";

public BasicAuthenticationProvider(final String openApiSpecId, String name, final AuthConfig authConfig,
List<OperationAuthInfo> operations) {
super(authConfig, name, openApiSpecId, operations);
public BasicAuthenticationProvider(final String openApiSpecId, String name, List<OperationAuthInfo> operations) {
super(name, openApiSpecId, operations);
validateConfig();
}

private String getUsername() {
return getAuthConfigParam(USER_NAME, "");
return ConfigProvider.getConfig().getOptionalValue(getCanonicalAuthConfigPropertyName(USER_NAME), String.class)
.orElse("");
}

private String getPassword() {
return getAuthConfigParam(PASSWORD, "");
return ConfigProvider.getConfig().getOptionalValue(getCanonicalAuthConfigPropertyName(PASSWORD), String.class)
.orElse("");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.core.HttpHeaders;

import io.quarkiverse.openapi.generator.AuthConfig;
import org.eclipse.microprofile.config.ConfigProvider;

/**
* Provides bearer token authentication or any other valid scheme.
Expand All @@ -20,8 +20,8 @@ public class BearerAuthenticationProvider extends AbstractAuthProvider {
private final String scheme;

public BearerAuthenticationProvider(final String openApiSpecId, final String name, final String scheme,
final AuthConfig authConfig, List<OperationAuthInfo> operations) {
super(authConfig, name, openApiSpecId, operations);
List<OperationAuthInfo> operations) {
super(name, openApiSpecId, operations);
this.scheme = scheme;
}

Expand All @@ -41,6 +41,7 @@ public void filter(ClientRequestContext requestContext) throws IOException {
}

private String getBearerToken() {
return getAuthConfigParam(BEARER_TOKEN, "");
return ConfigProvider.getConfig().getOptionalValue(getCanonicalAuthConfigPropertyName(BEARER_TOKEN), String.class)
.orElse("");
}
}
Loading

0 comments on commit b2c7c72

Please sign in to comment.