diff --git a/client/deployment/pom.xml b/client/deployment/pom.xml
index 1000a5af..fc8e22fa 100644
--- a/client/deployment/pom.xml
+++ b/client/deployment/pom.xml
@@ -118,7 +118,21 @@
quarkus-openapi-generator-test-utils
test
-
+
+ io.quarkus
+ quarkus-rest-client-oidc-filter
+ test
+
+
+ jakarta.ws.rs
+ jakarta.ws.rs-api
+ test
+
+
+ org.eclipse.microprofile.rest.client
+ microprofile-rest-client-api
+ test
+
io.quarkus
quarkus-junit5-internal
diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/AuthProviderBuildItem.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/AuthProviderBuildItem.java
new file mode 100644
index 00000000..652953ba
--- /dev/null
+++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/AuthProviderBuildItem.java
@@ -0,0 +1,22 @@
+package io.quarkiverse.openapi.generator.deployment;
+
+import io.quarkus.builder.item.MultiBuildItem;
+
+public final class AuthProviderBuildItem extends MultiBuildItem {
+
+ final String openApiSpecId;
+ final String name;
+
+ AuthProviderBuildItem(String openApiSpecId, String name) {
+ this.openApiSpecId = openApiSpecId;
+ this.name = name;
+ }
+
+ public String getOpenApiSpecId() {
+ return openApiSpecId;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/GeneratorProcessor.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/GeneratorProcessor.java
new file mode 100644
index 00000000..2cc8c3b3
--- /dev/null
+++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/GeneratorProcessor.java
@@ -0,0 +1,284 @@
+package io.quarkiverse.openapi.generator.deployment;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import jakarta.enterprise.context.Dependent;
+import jakarta.enterprise.inject.Instance;
+
+import org.jboss.jandex.AnnotationInstance;
+import org.jboss.jandex.ClassType;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.ParameterizedType;
+
+import io.quarkiverse.openapi.generator.AuthName;
+import io.quarkiverse.openapi.generator.AuthenticationRecorder;
+import io.quarkiverse.openapi.generator.ClassicOidcClientRequestFilterDelegate;
+import io.quarkiverse.openapi.generator.OidcClient;
+import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
+import io.quarkiverse.openapi.generator.OpenApiSpec;
+import io.quarkiverse.openapi.generator.ReactiveOidcClientRequestFilterDelegate;
+import io.quarkiverse.openapi.generator.markers.ApiKeyAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.BasicAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.BearerAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.OauthAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.OperationMarker;
+import io.quarkiverse.openapi.generator.providers.ApiKeyIn;
+import io.quarkiverse.openapi.generator.providers.AuthProvider;
+import io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate;
+import io.quarkiverse.openapi.generator.providers.OperationAuthInfo;
+import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.deployment.Capabilities;
+import io.quarkus.deployment.Capability;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+
+public class GeneratorProcessor {
+
+ private static final String FEATURE = "openapi-generator";
+ private static final DotName OAUTH_AUTHENTICATION_MARKER = DotName.createSimple(OauthAuthenticationMarker.class);
+ private static final DotName BASIC_AUTHENTICATION_MARKER = DotName.createSimple(BasicAuthenticationMarker.class);
+ private static final DotName BEARER_AUTHENTICATION_MARKER = DotName.createSimple(BearerAuthenticationMarker.class);
+ private static final DotName API_KEY_AUTHENTICATION_MARKER = DotName.createSimple(ApiKeyAuthenticationMarker.class);
+
+ private static final DotName OPERATION_MARKER = DotName.createSimple(OperationMarker.class);
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+
+ @BuildStep
+ void additionalBean(
+ Capabilities capabilities,
+ BuildProducer producer) {
+
+ if (capabilities.isPresent(Capability.REST_CLIENT_REACTIVE)) {
+ producer.produce(
+ AdditionalBeanBuildItem.builder().addBeanClass(ReactiveOidcClientRequestFilterDelegate.class)
+ .setDefaultScope(DotName.createSimple(Dependent.class))
+ .setUnremovable()
+ .build());
+ } else {
+ producer.produce(
+ AdditionalBeanBuildItem.builder().addBeanClass(ClassicOidcClientRequestFilterDelegate.class)
+ .setDefaultScope(DotName.createSimple(Dependent.class))
+ .setUnremovable()
+ .build());
+ }
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void produceCompositeProviders(AuthenticationRecorder recorder,
+ List authProviders,
+ BuildProducer beanProducer) {
+ Map> providersBySpec = authProviders.stream()
+ .collect(Collectors.groupingBy(AuthProviderBuildItem::getOpenApiSpecId));
+ providersBySpec.forEach((openApiSpecId, providers) -> {
+ beanProducer.produce(SyntheticBeanBuildItem.configure(CompositeAuthenticationProvider.class)
+ .scope(Dependent.class)
+ .addQualifier()
+ .annotation(OpenApiSpec.class)
+ .addValue("openApiSpecId", openApiSpecId)
+ .done()
+ .addInjectionPoint(
+ ParameterizedType.create(Instance.class, ClassType.create(AuthProvider.class)),
+ AnnotationInstance.builder(OpenApiSpec.class)
+ .add("openApiSpecId", openApiSpecId)
+ .build())
+ .createWith(recorder.recordCompositeProvider(openApiSpecId))
+ .done());
+
+ });
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void produceOauthAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
+ BuildProducer authenticationProviders,
+ BuildProducer beanProducer,
+ AuthenticationRecorder recorder) {
+ Collection authenticationMarkers = beanArchiveBuildItem.getIndex()
+ .getAnnotationsWithRepeatable(OAUTH_AUTHENTICATION_MARKER, beanArchiveBuildItem.getIndex());
+
+ Map> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);
+
+ for (AnnotationInstance authenticationMarker : authenticationMarkers) {
+ String name = authenticationMarker.value("name").asString();
+ String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();
+ List operations = getOperations(operationsBySpec, openApiSpecId, name);
+ authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));
+ beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
+ .scope(Dependent.class)
+ .addQualifier()
+ .annotation(AuthName.class)
+ .addValue("name", name)
+ .done()
+ .addQualifier()
+ .annotation(OpenApiSpec.class)
+ .addValue("openApiSpecId", openApiSpecId)
+ .done()
+ .addInjectionPoint(ClassType.create(OidcClientRequestFilterDelegate.class),
+ AnnotationInstance.builder(OidcClient.class)
+ .add("name", sanitizeAuthName(name))
+ .build())
+ .createWith(recorder.recordOauthAuthProvider(
+ sanitizeAuthName(name),
+ openApiSpecId,
+ operations))
+ .unremovable()
+ .done());
+ }
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void produceBasicAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
+ BuildProducer authenticationProviders,
+ BuildProducer beanProducer,
+ AuthenticationRecorder recorder) {
+
+ Collection authenticationMarkers = beanArchiveBuildItem.getIndex()
+ .getAnnotationsWithRepeatable(BASIC_AUTHENTICATION_MARKER, beanArchiveBuildItem.getIndex());
+
+ Map> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);
+ for (AnnotationInstance authenticationMarker : authenticationMarkers) {
+ String name = authenticationMarker.value("name").asString();
+ String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();
+
+ List operations = getOperations(operationsBySpec, openApiSpecId, name);
+
+ authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));
+
+ beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
+ .scope(Dependent.class)
+ .addQualifier()
+ .annotation(AuthName.class)
+ .addValue("name", name)
+ .done()
+ .addQualifier()
+ .annotation(OpenApiSpec.class)
+ .addValue("openApiSpecId", openApiSpecId)
+ .done()
+ .createWith(recorder.recordBasicAuthProvider(
+ sanitizeAuthName(name),
+ openApiSpecId,
+ operations))
+ .unremovable()
+ .done());
+ }
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void produceBearerAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
+ BuildProducer authenticationProviders,
+ BuildProducer beanProducer,
+ AuthenticationRecorder recorder) {
+
+ Collection authenticationMarkers = beanArchiveBuildItem.getIndex()
+ .getAnnotationsWithRepeatable(BEARER_AUTHENTICATION_MARKER, beanArchiveBuildItem.getIndex());
+
+ Map> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);
+ for (AnnotationInstance authenticationMarker : authenticationMarkers) {
+ String name = authenticationMarker.value("name").asString();
+ String scheme = authenticationMarker.value("scheme").asString();
+ String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();
+
+ List operations = getOperations(operationsBySpec, openApiSpecId, name);
+ authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));
+ beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
+ .scope(Dependent.class)
+ .addQualifier()
+ .annotation(AuthName.class)
+ .addValue("name", name)
+ .done()
+ .addQualifier()
+ .annotation(OpenApiSpec.class)
+ .addValue("openApiSpecId", openApiSpecId)
+ .done()
+ .createWith(recorder.recordBearerAuthProvider(
+ sanitizeAuthName(name),
+ scheme,
+ openApiSpecId,
+ operations))
+ .unremovable()
+ .done());
+
+ }
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void produceApiKeyAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
+ BuildProducer authenticationProviders,
+ BuildProducer beanProducer,
+ AuthenticationRecorder recorder) {
+
+ Collection authenticationMarkers = beanArchiveBuildItem.getIndex()
+ .getAnnotationsWithRepeatable(API_KEY_AUTHENTICATION_MARKER, beanArchiveBuildItem.getIndex());
+ Map> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);
+ for (AnnotationInstance authenticationMarker : authenticationMarkers) {
+ String name = authenticationMarker.value("name").asString();
+ String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();
+ String apiKeyName = authenticationMarker.value("apiKeyName").asString();
+ ApiKeyIn apiKeyIn = ApiKeyIn.valueOf(authenticationMarker.value("apiKeyIn").asEnum());
+
+ List operations = getOperations(operationsBySpec, openApiSpecId, name);
+
+ authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));
+
+ beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
+ .scope(Dependent.class)
+ .addQualifier()
+ .annotation(AuthName.class)
+ .addValue("name", name)
+ .done()
+ .addQualifier()
+ .annotation(OpenApiSpec.class)
+ .addValue("openApiSpecId", openApiSpecId)
+ .done()
+ .createWith(recorder.recordApiKeyAuthProvider(
+ sanitizeAuthName(name),
+ openApiSpecId,
+ apiKeyIn,
+ apiKeyName,
+ operations))
+ .unremovable()
+ .done());
+ }
+
+ }
+
+ private static String sanitizeAuthName(String schemeName) {
+ return OpenApiGeneratorConfig.getSanitizedSecuritySchemeName(schemeName);
+ }
+
+ private static Map> getOperationsBySpec(CombinedIndexBuildItem beanArchiveBuildItem) {
+ Map> operationsBySpec = beanArchiveBuildItem.getIndex()
+ .getAnnotationsWithRepeatable(OPERATION_MARKER, beanArchiveBuildItem.getIndex()).stream()
+ .collect(Collectors.groupingBy(
+ marker -> marker.value("openApiSpecId").asString() + "_" + marker.value("name").asString()));
+ return operationsBySpec;
+ }
+
+ private static List getOperations(Map> operationsBySpec,
+ String openApiSpecId, String name) {
+ return operationsBySpec.getOrDefault(openApiSpecId + "_" + name, List.of()).stream()
+ .map(op -> OperationAuthInfo.builder()
+ .withPath(op.value("path").asString())
+ .withId(op.value("operationId").asString())
+ .withMethod(op.value("method").asString())
+ .build())
+ .collect(Collectors.toList());
+ }
+}
diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute
index 190e1867..3d291e43 100644
--- a/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute
+++ b/client/deployment/src/main/resources/templates/libraries/microprofile/api.qute
@@ -33,6 +33,13 @@ public interface {classname} {
/**
{#include operationJavaDoc.qute op=op/}
*/
+ {#if op.hasAuthMethods}
+ {#for auth in op.authMethods}
+ @io.quarkiverse.openapi.generator.markers.OperationMarker(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}", operationId="{op.operationId}", method="{op.httpMethod}", path="{contextPath}{commonPath}{op.path.orEmpty}")
+ {/for}
+ {#else}
+ @io.quarkiverse.openapi.generator.markers.OperationMarker(name="{defaultSecurityScheme}", openApiSpecId="{quarkus-generator.openApiSpecId}", operationId="{op.operationId}", method="{op.httpMethod}", path="{contextPath}{commonPath}{op.path.orEmpty}")
+ {/if}
@jakarta.ws.rs.{op.httpMethod}
{#if op.subresourceOperation}
@jakarta.ws.rs.Path("{op.path}")
diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/auth/compositeAuthenticationProvider.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/auth/compositeAuthenticationProvider.qute
index 4732cf78..c1fd0798 100644
--- a/client/deployment/src/main/resources/templates/libraries/microprofile/auth/compositeAuthenticationProvider.qute
+++ b/client/deployment/src/main/resources/templates/libraries/microprofile/auth/compositeAuthenticationProvider.qute
@@ -1,204 +1,32 @@
package {apiPackage}.auth;
@jakarta.annotation.Priority(jakarta.ws.rs.Priorities.AUTHENTICATION)
-public class CompositeAuthenticationProvider extends io.quarkiverse.openapi.generator.providers.AbstractCompositeAuthenticationProvider {
+{#for auth in oauthMethods.orEmpty}
+@io.quarkiverse.openapi.generator.markers.OauthAuthenticationMarker(name="{auth.name}", openApiSpecId="{configKey}")
+{/for}
+{#for auth in httpBasicMethods.orEmpty}
+@io.quarkiverse.openapi.generator.markers.BasicAuthenticationMarker(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}")
+{/for}
+{#for auth in httpBearerMethods.orEmpty}
+@io.quarkiverse.openapi.generator.markers.BearerAuthenticationMarker(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}", scheme="{auth.scheme}")
+{/for}
+{#for auth in apiKeyMethods.orEmpty}
+{#if auth.isKeyInQuery}
+@io.quarkiverse.openapi.generator.markers.ApiKeyAuthenticationMarker(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}", apiKeyIn=io.quarkiverse.openapi.generator.providers.ApiKeyIn.query, apiKeyName="{auth.keyParamName}")
+{#else if auth.isKeyInHeader}
+@io.quarkiverse.openapi.generator.markers.ApiKeyAuthenticationMarker(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}", apiKeyIn=io.quarkiverse.openapi.generator.providers.ApiKeyIn.header, apiKeyName="{auth.keyParamName}")
+{#else if auth.isKeyInCookie}
+@io.quarkiverse.openapi.generator.markers.ApiKeyAuthenticationMarker(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}", apiKeyIn=io.quarkiverse.openapi.generator.providers.ApiKeyIn.cookie, apiKeyName="{auth.keyParamName}")
+{/if}
+{/for}
+public class CompositeAuthenticationProvider implements jakarta.ws.rs.client.ClientRequestFilter {
@jakarta.inject.Inject
- io.quarkiverse.openapi.generator.OpenApiGeneratorConfig generatorConfig;
+ @io.quarkiverse.openapi.generator.OpenApiSpec(openApiSpecId="{configKey}")
+ io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider compositeProvider;
- {#for auth in oauthMethods.orEmpty}
- @jakarta.inject.Inject
- io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider oAuth2Provider{auth_index};
-
- @jakarta.inject.Inject
- OidcClientRequestFilterDelegateImpl{auth_index} oidcClientRequestFilterDelegate{auth_index};
- {/for}
-
- @jakarta.annotation.PostConstruct
- public void init() {
- {#for auth in oauthMethods.orEmpty}
- oAuth2Provider{auth_index}.init(sanitizeAuthName("{auth.name}"), "{configKey}", oidcClientRequestFilterDelegate{auth_index});
- {/for}
-
- {#for auth in httpBasicMethods.orEmpty}
- io.quarkiverse.openapi.generator.providers.BasicAuthenticationProvider basicAuthProvider{auth_index} = new io.quarkiverse.openapi.generator.providers.BasicAuthenticationProvider("{quarkus-generator.openApiSpecId}", sanitizeAuthName("{auth.name}"), generatorConfig);
- this.addAuthenticationProvider(basicAuthProvider{auth_index});
- {#for api in apiInfo.apis}
- {#for op in api.operations.operation}
- {#if op.hasAuthMethods}
- {#for authM in op.authMethods}
- {#if authM.name == auth.name}
- basicAuthProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {#else if defaultSecurityScheme == auth.name}
- basicAuthProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {/for}
- {/for}
- {#for auth in oauthMethods.orEmpty}
- this.addAuthenticationProvider(oAuth2Provider{auth_index});
- {#for api in apiInfo.apis}
- {#for op in api.operations.operation}
- {#if op.hasAuthMethods}
- {#for authM in op.authMethods}
- {#if authM.name == auth.name}
- oAuth2Provider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {#else if defaultSecurityScheme == auth.name}
- oAuth2Provider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {/for}
- {/for}
- {#for auth in httpBearerMethods.orEmpty}
- io.quarkiverse.openapi.generator.providers.BearerAuthenticationProvider bearerProvider{auth_index} = new io.quarkiverse.openapi.generator.providers.BearerAuthenticationProvider("{quarkus-generator.openApiSpecId}", sanitizeAuthName("{auth.name}"), "{auth.scheme}", generatorConfig);
- this.addAuthenticationProvider(bearerProvider{auth_index});
- {#for api in apiInfo.apis}
- {#for op in api.operations.operation}
- {#if op.hasAuthMethods}
- {#for authM in op.authMethods}
- {#if authM.name == auth.name}
- bearerProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {#else if defaultSecurityScheme == auth.name}
- bearerProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {/for}
- {/for}
- {#for auth in apiKeyMethods.orEmpty}
- {#if auth.isKeyInQuery}
- io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider apiKeyQueryProvider{auth_index} = new io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider("{quarkus-generator.openApiSpecId}", sanitizeAuthName("{auth.name}"), io.quarkiverse.openapi.generator.providers.ApiKeyIn.query, "{auth.keyParamName}", generatorConfig);
- this.addAuthenticationProvider(apiKeyQueryProvider{auth_index});
- {#for api in apiInfo.apis}
- {#for op in api.operations.operation}
- {#if op.hasAuthMethods}
- {#for authM in op.authMethods}
- {#if authM.name == auth.name}
- apiKeyQueryProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {#else if defaultSecurityScheme == auth.name}
- apiKeyQueryProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {/for}
- {/if}
- {#if auth.isKeyInHeader}
- io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider apiKeyHeaderProvider{auth_index} = new io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider("{quarkus-generator.openApiSpecId}", sanitizeAuthName("{auth.name}"), io.quarkiverse.openapi.generator.providers.ApiKeyIn.header, "{auth.keyParamName}", generatorConfig);
- this.addAuthenticationProvider(apiKeyHeaderProvider{auth_index});
- {#for api in apiInfo.apis}
- {#for op in api.operations.operation}
- {#if op.hasAuthMethods}
- {#for authM in op.authMethods}
- {#if authM.name == auth.name}
- apiKeyHeaderProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {#else if defaultSecurityScheme == auth.name}
- apiKeyHeaderProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {/for}
- {/if}
- {#if auth.isKeyInCookie}
- io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider apiKeyCookieProvider{auth_index} = new io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider("{quarkus-generator.openApiSpecId}", sanitizeAuthName("{auth.name}"), io.quarkiverse.openapi.generator.providers.ApiKeyIn.cookie, "{auth.keyParamName}", generatorConfig);
- this.addAuthenticationProvider(apiKeyCookieProvider{auth_index});
- {#for api in apiInfo.apis}
- {#for op in api.operations.operation}
- {#if op.hasAuthMethods}
- {#for authM in op.authMethods}
- {#if authM.name == auth.name}
- apiKeyCookieProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {#else if defaultSecurityScheme == auth.name}
- apiKeyCookieProvider{auth_index}.addOperation(io.quarkiverse.openapi.generator.providers.OperationAuthInfo.builder()
- .withPath("{api.contextPath}{api.commonPath}{op.path.orEmpty}")
- .withId("{op.operationId}")
- .withMethod("{op.httpMethod}")
- .build());
- {/if}
- {/for}
- {/for}
- {/if}
- {/for}
- }
-
- {#for auth in oauthMethods.orEmpty}
- @jakarta.enterprise.context.Dependent
- {#if is-resteasy-reactive}
- static class OidcClientRequestFilterDelegateImpl{auth_index} extends io.quarkus.oidc.client.reactive.filter.OidcClientRequestReactiveFilter implements io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate {
-
- private final String clientId = io.quarkiverse.openapi.generator.OpenApiGeneratorConfig.getSanitizedSecuritySchemeName("{auth.name}");
-
- @Override
- protected java.util.Optional clientId() {
- return java.util.Optional.of(clientId);
- }
-
- @Override
- public void filter(jakarta.ws.rs.client.ClientRequestContext requestContext) throws java.io.IOException {
- filter((org.jboss.resteasy.reactive.client.spi.ResteasyReactiveClientRequestContext)requestContext);
- }
- }
- {#else}
- static class OidcClientRequestFilterDelegateImpl{auth_index} extends io.quarkus.oidc.client.filter.OidcClientRequestFilter implements io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate {
- private final String clientId = io.quarkiverse.openapi.generator.OpenApiGeneratorConfig.getSanitizedSecuritySchemeName("{auth.name}");
-
- @Override
- protected java.util.Optional clientId() {
- return java.util.Optional.of(clientId);
- }
- }
- {/if}
- {/for}
+ @java.lang.Override
+ public void filter(jakarta.ws.rs.client.ClientRequestContext context) throws java.io.IOException {
+ compositeProvider.filter(context);
+ };
}
diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/auth/headersFactory.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/auth/headersFactory.qute
index 3b541c82..0fc3f221 100644
--- a/client/deployment/src/main/resources/templates/libraries/microprofile/auth/headersFactory.qute
+++ b/client/deployment/src/main/resources/templates/libraries/microprofile/auth/headersFactory.qute
@@ -3,7 +3,7 @@ package {apiPackage}.auth;
public class AuthenticationPropagationHeadersFactory extends io.quarkiverse.openapi.generator.providers.AbstractAuthenticationPropagationHeadersFactory {
@jakarta.inject.Inject
- public AuthenticationPropagationHeadersFactory(CompositeAuthenticationProvider compositeProvider, io.quarkiverse.openapi.generator.OpenApiGeneratorConfig generatorConfig, io.quarkiverse.openapi.generator.providers.HeadersProvider headersProvider) {
+ public AuthenticationPropagationHeadersFactory(@io.quarkiverse.openapi.generator.OpenApiSpec(openApiSpecId="{configKey}") io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider compositeProvider, io.quarkiverse.openapi.generator.OpenApiGeneratorConfig generatorConfig, io.quarkiverse.openapi.generator.providers.HeadersProvider headersProvider) {
super(compositeProvider, generatorConfig, headersProvider);
}
diff --git a/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/authentication/OpenApiSpecProviderTest.java b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/authentication/OpenApiSpecProviderTest.java
new file mode 100644
index 00000000..cf3e03c4
--- /dev/null
+++ b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/authentication/OpenApiSpecProviderTest.java
@@ -0,0 +1,93 @@
+package io.quarkiverse.openapi.generator.deployment.authentication;
+
+import static io.quarkiverse.openapi.generator.providers.ApiKeyIn.header;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import jakarta.annotation.Priority;
+import jakarta.inject.Inject;
+
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkiverse.openapi.generator.OpenApiSpec;
+import io.quarkiverse.openapi.generator.markers.ApiKeyAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.BasicAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.OauthAuthenticationMarker;
+import io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.AuthProvider;
+import io.quarkiverse.openapi.generator.providers.BasicAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider;
+import io.quarkus.test.QuarkusUnitTest;
+
+public class OpenApiSpecProviderTest {
+
+ @RegisterExtension
+ static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
+ .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
+ .addClass(LocalAuthenticationProvider.class)
+ .addAsResource(
+ new StringAsset("""
+ quarkus.oidc-client.oauth_auth.auth-server-url=localhost
+ quarkus.oidc-client.oauth_auth1.auth-server-url=localhost
+ quarkus.oidc-client.oauth_auth2.auth-server-url=localhost
+ """),
+ "application.properties"));
+
+ @Inject
+ @OpenApiSpec(openApiSpecId = "spec_1")
+ CompositeAuthenticationProvider spec1CompositeProvider;
+
+ @Inject
+ @OpenApiSpec(openApiSpecId = "spec_2")
+ CompositeAuthenticationProvider spec2CompositeProvider;
+
+ @Inject
+ @OpenApiSpec(openApiSpecId = "spec_3")
+ CompositeAuthenticationProvider spec3CompositeProvider;
+
+ @Inject
+ @OpenApiSpec(openApiSpecId = "spec_multi")
+ CompositeAuthenticationProvider multiCompositeProvider;
+
+ @Test
+ public void checkCompositeProvider() {
+ assertThat(spec1CompositeProvider.getAuthenticationProviders()).hasSize(1);
+ assertThat(spec2CompositeProvider.getAuthenticationProviders()).hasSize(1);
+ assertThat(spec3CompositeProvider.getAuthenticationProviders()).hasSize(1);
+ AuthProvider authProvider = spec1CompositeProvider.getAuthenticationProviders().get(0);
+ assertThat(authProvider).isInstanceOf(OAuth2AuthenticationProvider.class);
+ assertThat(authProvider.getName()).isEqualTo("oauth_auth");
+ assertThat(((OAuth2AuthenticationProvider) authProvider).getOpenApiSpecId()).isEqualTo("spec_1");
+ authProvider = spec2CompositeProvider.getAuthenticationProviders().get(0);
+ assertThat(authProvider).isInstanceOf(BasicAuthenticationProvider.class);
+ assertThat(authProvider.getName()).isEqualTo("basic_auth");
+ assertThat(((BasicAuthenticationProvider) authProvider).getOpenApiSpecId()).isEqualTo("spec_2");
+ authProvider = spec3CompositeProvider.getAuthenticationProviders().get(0);
+ assertThat(authProvider).isInstanceOf(ApiKeyAuthenticationProvider.class);
+ assertThat(authProvider.getName()).isEqualTo("api_key");
+ assertThat(((ApiKeyAuthenticationProvider) authProvider).getOpenApiSpecId()).isEqualTo("spec_3");
+ }
+
+ @Test
+ public void checkCompositeProviderWithMultipleAuth() {
+ Assertions.assertEquals(4, multiCompositeProvider.getAuthenticationProviders().size());
+ }
+
+ @Priority(jakarta.ws.rs.Priorities.AUTHENTICATION)
+ @OauthAuthenticationMarker(name = "oauth_auth", openApiSpecId = "spec_1")
+ @BasicAuthenticationMarker(name = "basic_auth", openApiSpecId = "spec_2")
+ @ApiKeyAuthenticationMarker(name = "api_key", openApiSpecId = "spec_3", apiKeyIn = header, apiKeyName = "api_key")
+ @OauthAuthenticationMarker(name = "oauth_auth1", openApiSpecId = "spec_multi")
+ @OauthAuthenticationMarker(name = "oauth_auth2", openApiSpecId = "spec_multi")
+ @BasicAuthenticationMarker(name = "basic_auth1", openApiSpecId = "spec_multi")
+ @BasicAuthenticationMarker(name = "basic_auth2", openApiSpecId = "spec_multi")
+ public static class LocalAuthenticationProvider {
+
+ }
+
+}
diff --git a/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/authentication/OperationTest.java b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/authentication/OperationTest.java
new file mode 100644
index 00000000..ea2f7e4f
--- /dev/null
+++ b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/authentication/OperationTest.java
@@ -0,0 +1,77 @@
+package io.quarkiverse.openapi.generator.deployment.authentication;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkiverse.openapi.generator.OpenApiSpec;
+import io.quarkiverse.openapi.generator.annotations.GeneratedClass;
+import io.quarkiverse.openapi.generator.markers.BasicAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.OauthAuthenticationMarker;
+import io.quarkiverse.openapi.generator.markers.OperationMarker;
+import io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.OperationAuthInfo;
+import io.quarkus.test.QuarkusUnitTest;
+
+public class OperationTest {
+
+ @RegisterExtension
+ static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
+ .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
+ .addClass(PetApi.class)
+ .addClass(LocalAuthenticationProvider.class)
+ .addAsResource(
+ new StringAsset("quarkus.oidc-client.oauth_auth.auth-server-url=localhost\n"),
+ "application.properties"));
+
+ @Inject
+ @OpenApiSpec(openApiSpecId = "petstore_json")
+ CompositeAuthenticationProvider compositeProvider;
+ @Inject
+ @OpenApiSpec(openApiSpecId = "other_spec_json")
+ CompositeAuthenticationProvider otherProvider;
+
+ @Test
+ public void test() {
+ assertThat(compositeProvider.getAuthenticationProviders()).hasSize(1);
+ assertThat(compositeProvider.getAuthenticationProviders().get(0).operationsToFilter()).hasSize(1);
+ assertThat(otherProvider.getAuthenticationProviders()).hasSize(1);
+ assertThat(otherProvider.getAuthenticationProviders().get(0).operationsToFilter()).isEmpty();
+ OperationAuthInfo operation = compositeProvider.getAuthenticationProviders().get(0).operationsToFilter().get(0);
+ assertThat(operation.getOperationId()).isEqualTo("addPet");
+ assertThat(operation.getHttpMethod()).isEqualTo("POST");
+ assertThat(operation.getPath()).isEqualTo("/api/v3/method1");
+
+ }
+
+ @RegisterRestClient(baseUri = "http://localhost/api/v3", configKey = "petstore_json")
+ @GeneratedClass(value = "petstore.json", tag = "Pet")
+ @ApplicationScoped
+ public interface PetApi {
+
+ @OperationMarker(name = "oauth_auth", openApiSpecId = "petstore_json", operationId = "addPet", method = "POST", path = "/api/v3/method1")
+ @Path("/method1")
+ @POST
+ Response method1();
+
+ }
+
+ @jakarta.annotation.Priority(jakarta.ws.rs.Priorities.AUTHENTICATION)
+ @OauthAuthenticationMarker(name = "oauth_auth", openApiSpecId = "petstore_json")
+ @BasicAuthenticationMarker(name = "basic_auth", openApiSpecId = "other_spec_json")
+ public static class LocalAuthenticationProvider {
+
+ }
+
+}
diff --git a/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java
index 0bd4002c..aba0d4fd 100644
--- a/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java
+++ b/client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java
@@ -98,15 +98,13 @@ void verifyAuthBasicWithMissingSecurityDefinition(String defaultSecurityScheme)
assertThat(methodDeclarations).isNotEmpty();
Optional initMethod = methodDeclarations.stream()
- .filter(m -> m.getNameAsString().equals("init"))
+ .filter(m -> m.getNameAsString().equals("filter"))
.findAny();
assertThat(initMethod).isPresent();
String fileContent = compilationUnit.toString();
- assertTrue(fileContent.contains("addAuthenticationProvider"));
- if (!defaultSecurityScheme.equals("undefined")) {
- assertTrue(fileContent.contains("addOperation"));
- }
+ assertTrue(fileContent.contains(
+ "@io.quarkiverse.openapi.generator.markers.BasicAuthenticationMarker(name = \"basic\", openApiSpecId = \"petstore_openapi_httpbasic_json\")"));
}
@Test
diff --git a/client/integration-tests/generation-tests/src/test/java/io/quarkiverse/openapi/generator/it/PetStoreTest.java b/client/integration-tests/generation-tests/src/test/java/io/quarkiverse/openapi/generator/it/PetStoreTest.java
index 8770ab1e..f0fe1edf 100644
--- a/client/integration-tests/generation-tests/src/test/java/io/quarkiverse/openapi/generator/it/PetStoreTest.java
+++ b/client/integration-tests/generation-tests/src/test/java/io/quarkiverse/openapi/generator/it/PetStoreTest.java
@@ -14,11 +14,11 @@
import com.github.tomakehurst.wiremock.WireMockServer;
import io.quarkiverse.openapi.generator.testutils.keycloak.KeycloakRealmResourceManager;
-import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.common.WithTestResource;
import io.quarkus.test.junit.QuarkusTest;
-@QuarkusTestResource(WiremockPetStore.class)
-@QuarkusTestResource(KeycloakRealmResourceManager.class)
+@WithTestResource(WiremockPetStore.class)
+@WithTestResource(KeycloakRealmResourceManager.class)
@QuarkusTest
public class PetStoreTest {
diff --git a/client/integration-tests/pom.xml b/client/integration-tests/pom.xml
index 873d2d8d..77b074f4 100644
--- a/client/integration-tests/pom.xml
+++ b/client/integration-tests/pom.xml
@@ -67,7 +67,7 @@
io.quarkus
- quarkus-oidc-client-filter
+ quarkus-resteasy-client-oidc-filter
io.quarkus
@@ -98,11 +98,11 @@
io.quarkus
- quarkus-rest-client-reactive-jackson
+ quarkus-rest-client-jackson
io.quarkus
- quarkus-oidc-client-reactive-filter
+ quarkus-rest-client-oidc-filter
jakarta.validation
diff --git a/client/integration-tests/security/src/main/java/io/quarkiverse/openapi/generator/it/security/auth/DummyApiKeyAuthenticationProvider.java b/client/integration-tests/security/src/main/java/io/quarkiverse/openapi/generator/it/security/auth/DummyApiKeyAuthenticationProvider.java
index a04f8371..3e353d93 100644
--- a/client/integration-tests/security/src/main/java/io/quarkiverse/openapi/generator/it/security/auth/DummyApiKeyAuthenticationProvider.java
+++ b/client/integration-tests/security/src/main/java/io/quarkiverse/openapi/generator/it/security/auth/DummyApiKeyAuthenticationProvider.java
@@ -1,6 +1,7 @@
package io.quarkiverse.openapi.generator.it.security.auth;
import java.io.IOException;
+import java.util.List;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Priority;
@@ -10,6 +11,7 @@
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;
@@ -25,7 +27,9 @@ public class DummyApiKeyAuthenticationProvider implements ClientRequestFilter {
@PostConstruct
public void init() {
authProvider = new ApiKeyAuthenticationProvider("open_weather_custom_security_yaml", "app_id", ApiKeyIn.query, "appid",
- generatorConfig);
+ generatorConfig.getItemConfig("open_weather_custom_security_yaml")
+ .flatMap(SpecItemConfig::getAuth).flatMap(x -> x.getItemConfig("app_id")).orElse(null),
+ List.of());
}
@Override
diff --git a/client/runtime/pom.xml b/client/runtime/pom.xml
index 24dd902a..b0b2ab4a 100644
--- a/client/runtime/pom.xml
+++ b/client/runtime/pom.xml
@@ -39,8 +39,13 @@
io.quarkus
- quarkus-oidc-client-filter
- test
+ quarkus-rest-client-oidc-filter
+ true
+
+
+ io.quarkus
+ quarkus-resteasy-client-oidc-filter
+ true
org.assertj
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/AuthName.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/AuthName.java
new file mode 100644
index 00000000..60b01628
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/AuthName.java
@@ -0,0 +1,21 @@
+package io.quarkiverse.openapi.generator;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import jakarta.inject.Qualifier;
+
+@Qualifier
+@Retention(RUNTIME)
+@Target({ METHOD, FIELD, PARAMETER, TYPE })
+public @interface AuthName {
+
+ String name();
+
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/AuthenticationRecorder.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/AuthenticationRecorder.java
new file mode 100644
index 00000000..c94127ed
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/AuthenticationRecorder.java
@@ -0,0 +1,83 @@
+package io.quarkiverse.openapi.generator;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+
+import jakarta.enterprise.inject.Instance;
+import jakarta.enterprise.util.TypeLiteral;
+
+import io.quarkiverse.openapi.generator.OpenApiSpec.Literal;
+import io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.ApiKeyIn;
+import io.quarkiverse.openapi.generator.providers.AuthProvider;
+import io.quarkiverse.openapi.generator.providers.BasicAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.BearerAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider;
+import io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate;
+import io.quarkiverse.openapi.generator.providers.OperationAuthInfo;
+import io.quarkus.arc.SyntheticCreationalContext;
+import io.quarkus.runtime.annotations.Recorder;
+
+@Recorder
+public class AuthenticationRecorder {
+
+ final OpenApiGeneratorConfig generatorConfig;
+
+ public AuthenticationRecorder(OpenApiGeneratorConfig generatorConfig) {
+ this.generatorConfig = generatorConfig;
+ }
+
+ public Function, CompositeAuthenticationProvider> recordCompositeProvider(
+ String openApiSpec) {
+ return ctx -> {
+ List providers = ctx.getInjectedReference(new TypeLiteral>() {
+ }, new Literal(openApiSpec)).stream().toList();
+ return new CompositeAuthenticationProvider(providers);
+ };
+ }
+
+ public Function, AuthProvider> recordApiKeyAuthProvider(
+ String name,
+ String openApiSpecId,
+ ApiKeyIn apiKeyIn,
+ String apiKeyName,
+ List operations) {
+ return context -> new ApiKeyAuthenticationProvider(openApiSpecId, name, apiKeyIn, apiKeyName,
+ getAuthConfig(openApiSpecId, name),
+ operations);
+ }
+
+ public Function, AuthProvider> recordBearerAuthProvider(
+ String name,
+ String scheme,
+ String openApiSpecId,
+ List operations) {
+ return context -> new BearerAuthenticationProvider(openApiSpecId, name, scheme, getAuthConfig(openApiSpecId, name),
+ operations);
+ }
+
+ public Function, AuthProvider> recordBasicAuthProvider(
+ String name,
+ String openApiSpecId,
+ List operations) {
+ return context -> new BasicAuthenticationProvider(openApiSpecId, name, getAuthConfig(openApiSpecId, name), operations);
+ }
+
+ public Function, AuthProvider> recordOauthAuthProvider(
+ String name,
+ String openApiSpecId,
+ List operations) {
+ return context -> new OAuth2AuthenticationProvider(getAuthConfig(openApiSpecId, name), name, openApiSpecId,
+ context.getInjectedReference(OidcClientRequestFilterDelegate.class, new OidcClient.Literal(name)), operations);
+ }
+
+ AuthConfig getAuthConfig(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);
+ }
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/ClassicOidcClientRequestFilterDelegate.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/ClassicOidcClientRequestFilterDelegate.java
new file mode 100644
index 00000000..9f25d105
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/ClassicOidcClientRequestFilterDelegate.java
@@ -0,0 +1,56 @@
+package io.quarkiverse.openapi.generator;
+
+import java.io.IOException;
+
+import jakarta.annotation.Priority;
+import jakarta.enterprise.inject.spi.InjectionPoint;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+
+import org.jboss.logging.Logger;
+
+import io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider;
+import io.quarkus.oidc.client.runtime.AbstractTokensProducer;
+import io.quarkus.oidc.client.runtime.DisabledOidcClientException;
+
+@Priority(Priorities.AUTHENTICATION)
+@OidcClient
+public class ClassicOidcClientRequestFilterDelegate extends AbstractTokensProducer
+ implements ClientRequestFilter, OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate {
+
+ private static final Logger LOG = Logger
+ .getLogger(ClassicOidcClientRequestFilterDelegate.class);
+
+ final String clientId;
+
+ ClassicOidcClientRequestFilterDelegate(InjectionPoint injectionPoint) {
+ OidcClient annotation = (OidcClient) injectionPoint.getQualifiers().stream()
+ .filter(x -> x.annotationType().equals(OidcClient.class))
+ .findFirst().orElseThrow();
+
+ this.clientId = OpenApiGeneratorConfig.getSanitizedSecuritySchemeName(annotation.name());
+ }
+
+ @Override
+ protected java.util.Optional clientId() {
+ return java.util.Optional.of(clientId);
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ try {
+ String accessToken = this.getAccessToken();
+ requestContext.getHeaders().add("Authorization", "Bearer " + accessToken);
+ } catch (DisabledOidcClientException ex) {
+ LOG.debug("Client is disabled, acquiring and propagating the token is not necessary");
+ } catch (RuntimeException ex) {
+ LOG.debugf("Access token is not available, cause: %s, aborting the request", ex.getMessage());
+ throw ex;
+ }
+ }
+
+ private String getAccessToken() {
+ return this.awaitTokens().getAccessToken();
+ }
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OidcClient.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OidcClient.java
new file mode 100644
index 00000000..6861ba1e
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OidcClient.java
@@ -0,0 +1,38 @@
+package io.quarkiverse.openapi.generator;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import jakarta.enterprise.util.AnnotationLiteral;
+import jakarta.enterprise.util.Nonbinding;
+import jakarta.inject.Qualifier;
+
+@Qualifier
+@Retention(RUNTIME)
+@Target({ METHOD, FIELD, PARAMETER, TYPE })
+public @interface OidcClient {
+
+ String DEFAULT = "io.quarkiverse.openapi.generator.DEFAULT";
+
+ @Nonbinding
+ String name() default DEFAULT;
+
+ final class Literal extends AnnotationLiteral implements OidcClient {
+ public Literal(String name) {
+ this.name = name;
+ }
+
+ final String name;
+
+ @Override
+ public String name() {
+ return name;
+ }
+ }
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OpenApiGeneratorConfig.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OpenApiGeneratorConfig.java
index 6b297f57..88454d1f 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OpenApiGeneratorConfig.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OpenApiGeneratorConfig.java
@@ -11,7 +11,7 @@
/**
* This class represents the runtime configurations for the openapi-generator extension.
*/
-@ConfigRoot(name = OpenApiGeneratorConfig.RUNTIME_TIME_CONFIG_PREFIX, phase = ConfigPhase.RUN_TIME)
+@ConfigRoot(name = OpenApiGeneratorConfig.RUNTIME_TIME_CONFIG_PREFIX, phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public class OpenApiGeneratorConfig {
public static final String RUNTIME_TIME_CONFIG_PREFIX = "openapi-generator";
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OpenApiSpec.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OpenApiSpec.java
new file mode 100644
index 00000000..7c45afe6
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/OpenApiSpec.java
@@ -0,0 +1,34 @@
+package io.quarkiverse.openapi.generator;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import jakarta.enterprise.util.AnnotationLiteral;
+import jakarta.inject.Qualifier;
+
+@Qualifier
+@Retention(RUNTIME)
+@Target({ METHOD, FIELD, PARAMETER, TYPE })
+public @interface OpenApiSpec {
+
+ String openApiSpecId();
+
+ final class Literal extends AnnotationLiteral implements OpenApiSpec {
+ public Literal(String openApiSpecId) {
+ this.openApiSpecId = openApiSpecId;
+ }
+
+ final String openApiSpecId;
+
+ @Override
+ public String openApiSpecId() {
+ return openApiSpecId;
+ }
+ }
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/ReactiveOidcClientRequestFilterDelegate.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/ReactiveOidcClientRequestFilterDelegate.java
new file mode 100644
index 00000000..d4fb3f4d
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/ReactiveOidcClientRequestFilterDelegate.java
@@ -0,0 +1,81 @@
+package io.quarkiverse.openapi.generator;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import jakarta.annotation.Priority;
+import jakarta.enterprise.inject.spi.InjectionPoint;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.HttpHeaders;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.reactive.client.spi.ResteasyReactiveClientRequestContext;
+import org.jboss.resteasy.reactive.client.spi.ResteasyReactiveClientRequestFilter;
+
+import io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider;
+import io.quarkus.oidc.client.Tokens;
+import io.quarkus.oidc.client.runtime.AbstractTokensProducer;
+import io.quarkus.oidc.client.runtime.DisabledOidcClientException;
+import io.quarkus.oidc.common.runtime.OidcConstants;
+
+@Priority(Priorities.AUTHENTICATION)
+@OidcClient
+public class ReactiveOidcClientRequestFilterDelegate extends AbstractTokensProducer
+ implements ResteasyReactiveClientRequestFilter, OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate {
+
+ private static final Logger LOG = Logger
+ .getLogger(ReactiveOidcClientRequestFilterDelegate.class);
+ private static final String BEARER_SCHEME_WITH_SPACE = OidcConstants.BEARER_SCHEME + " ";
+
+ final String clientId;
+
+ ReactiveOidcClientRequestFilterDelegate(InjectionPoint injectionPoint) {
+ OidcClient annotation = (OidcClient) injectionPoint.getQualifiers().stream()
+ .filter(x -> x.annotationType().equals(OidcClient.class))
+ .findFirst().orElseThrow();
+ this.clientId = OpenApiGeneratorConfig.getSanitizedSecuritySchemeName(annotation.name());
+ }
+
+ @Override
+ protected java.util.Optional clientId() {
+ return java.util.Optional.of(clientId);
+ }
+
+ @Override
+ protected void initTokens() {
+ if (earlyTokenAcquisition) {
+ LOG.debug("Token acquisition will be delayed until this filter is executed to avoid blocking an IO thread");
+ }
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ filter((ResteasyReactiveClientRequestContext) requestContext);
+ }
+
+ @Override
+ public void filter(ResteasyReactiveClientRequestContext requestContext) {
+ requestContext.suspend();
+
+ super.getTokens().subscribe().with(new Consumer<>() {
+ @Override
+ public void accept(Tokens tokens) {
+ requestContext.getHeaders().putSingle(HttpHeaders.AUTHORIZATION,
+ BEARER_SCHEME_WITH_SPACE + tokens.getAccessToken());
+ requestContext.resume();
+ }
+ }, new Consumer<>() {
+ @Override
+ public void accept(Throwable t) {
+ if (t instanceof DisabledOidcClientException) {
+ LOG.debug("Client is disabled, acquiring and propagating the token is not necessary");
+ requestContext.resume();
+ } else {
+ LOG.debugf("Access token is not available, cause: %s, aborting the request", t.getMessage());
+ requestContext.resume((t instanceof RuntimeException) ? t : new RuntimeException(t));
+ }
+ }
+ });
+ }
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/ApiKeyAuthenticationMarker.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/ApiKeyAuthenticationMarker.java
new file mode 100644
index 00000000..3880174b
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/ApiKeyAuthenticationMarker.java
@@ -0,0 +1,31 @@
+package io.quarkiverse.openapi.generator.markers;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import io.quarkiverse.openapi.generator.providers.ApiKeyIn;
+
+@Target(TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(ApiKeyAuthenticationMarker.AuthenticationMarkers.class)
+public @interface ApiKeyAuthenticationMarker {
+
+ String name();
+
+ String openApiSpecId();
+
+ ApiKeyIn apiKeyIn();
+
+ String apiKeyName();
+
+ @Target(TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface AuthenticationMarkers {
+ ApiKeyAuthenticationMarker[] value();
+ }
+
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/BasicAuthenticationMarker.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/BasicAuthenticationMarker.java
new file mode 100644
index 00000000..cd5e8108
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/BasicAuthenticationMarker.java
@@ -0,0 +1,25 @@
+package io.quarkiverse.openapi.generator.markers;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(BasicAuthenticationMarker.AuthenticationMarkers.class)
+public @interface BasicAuthenticationMarker {
+
+ String name();
+
+ String openApiSpecId();
+
+ @Target(TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface AuthenticationMarkers {
+ BasicAuthenticationMarker[] value();
+ }
+
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/BearerAuthenticationMarker.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/BearerAuthenticationMarker.java
new file mode 100644
index 00000000..622540e1
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/BearerAuthenticationMarker.java
@@ -0,0 +1,27 @@
+package io.quarkiverse.openapi.generator.markers;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(BearerAuthenticationMarker.AuthenticationMarkers.class)
+public @interface BearerAuthenticationMarker {
+
+ String name();
+
+ String openApiSpecId();
+
+ String scheme();
+
+ @Target(TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface AuthenticationMarkers {
+ BearerAuthenticationMarker[] value();
+ }
+
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/OauthAuthenticationMarker.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/OauthAuthenticationMarker.java
new file mode 100644
index 00000000..3d212333
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/OauthAuthenticationMarker.java
@@ -0,0 +1,25 @@
+package io.quarkiverse.openapi.generator.markers;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(OauthAuthenticationMarker.AuthenticationMarkers.class)
+public @interface OauthAuthenticationMarker {
+
+ String name();
+
+ String openApiSpecId();
+
+ @Target(TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface AuthenticationMarkers {
+ OauthAuthenticationMarker[] value();
+ }
+
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/OperationMarker.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/OperationMarker.java
new file mode 100644
index 00000000..1caa6723
--- /dev/null
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/markers/OperationMarker.java
@@ -0,0 +1,31 @@
+package io.quarkiverse.openapi.generator.markers;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(OperationMarker.OperationMarkers.class)
+public @interface OperationMarker {
+
+ String name();
+
+ String openApiSpecId();
+
+ String operationId();
+
+ String path();
+
+ String method();
+
+ @Target(METHOD)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface OperationMarkers {
+ OperationMarker[] value();
+ }
+
+}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthProvider.java
index 5cea1954..1ede697f 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthProvider.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthProvider.java
@@ -6,15 +6,11 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
-import java.util.Optional;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MultivaluedMap;
import io.quarkiverse.openapi.generator.AuthConfig;
-import io.quarkiverse.openapi.generator.AuthsConfig;
-import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
-import io.quarkiverse.openapi.generator.SpecItemConfig;
public abstract class AbstractAuthProvider implements AuthProvider {
@@ -22,36 +18,17 @@ public abstract class AbstractAuthProvider implements AuthProvider {
private static final String CANONICAL_AUTH_CONFIG_PROPERTY_NAME = "quarkus." +
RUNTIME_TIME_CONFIG_PREFIX + ".%s.auth.%s.%s";
- private String openApiSpecId;
- private String name;
- private final OpenApiGeneratorConfig generatorConfig;
- private AuthConfig authConfig;
+ private final String openApiSpecId;
+ private final String name;
+ private final AuthConfig authConfig;
private final List applyToOperations = new ArrayList<>();
- protected AbstractAuthProvider() {
- // Required by CDI. Not supposed to be used.
- name = null;
- generatorConfig = null;
- }
-
- protected AbstractAuthProvider(OpenApiGeneratorConfig generatorConfig) {
- this.generatorConfig = generatorConfig;
- }
-
- protected void init(String name, String openApiSpecId) {
+ protected AbstractAuthProvider(AuthConfig authConfig, String name, String openApiSpecId,
+ List operations) {
this.name = name;
- setOpenApiSpecId(openApiSpecId);
- }
-
- private void setOpenApiSpecId(String openApiSpecId) {
this.openApiSpecId = openApiSpecId;
- Optional specItemConfig = Objects.requireNonNull(generatorConfig, "generatorConfig can't be null.")
- .getItemConfig(openApiSpecId);
- if (specItemConfig.isPresent()) {
- Optional authsConfig = specItemConfig.get().getAuth();
- authsConfig.ifPresent(
- specItemAuthsConfig -> authConfig = specItemAuthsConfig.getItemConfig(name).orElse(null));
- }
+ this.authConfig = authConfig;
+ this.applyToOperations.addAll(operations);
}
public String getOpenApiSpecId() {
@@ -63,10 +40,6 @@ public String getName() {
return name;
}
- public OpenApiGeneratorConfig getGeneratorConfig() {
- return generatorConfig;
- }
-
public boolean isTokenPropagation() {
return authConfig != null && authConfig.getTokenPropagation().orElse(false);
}
@@ -89,12 +62,6 @@ public List operationsToFilter() {
return applyToOperations;
}
- @Override
- public AuthProvider addOperation(OperationAuthInfo operationAuthInfo) {
- this.applyToOperations.add(operationAuthInfo);
- return this;
- }
-
public String getAuthConfigParam(String paramName, String defaultValue) {
if (authConfig != null) {
return authConfig.getConfigParam(paramName).orElse(defaultValue);
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthenticationPropagationHeadersFactory.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthenticationPropagationHeadersFactory.java
index e96cff5e..586e14c7 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthenticationPropagationHeadersFactory.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractAuthenticationPropagationHeadersFactory.java
@@ -19,11 +19,11 @@ public abstract class AbstractAuthenticationPropagationHeadersFactory implements
private static final String HEADER_NAME_PREFIX_FOR_TOKEN_PROPAGATION = "QCG_%s";
private static final String HEADER_NAME_FOR_TOKEN_PROPAGATION = "QCG_%s_%s_%s";
- protected AbstractCompositeAuthenticationProvider compositeProvider;
+ protected CompositeAuthenticationProvider compositeProvider;
protected OpenApiGeneratorConfig generatorConfig;
protected HeadersProvider headersProvider;
- protected AbstractAuthenticationPropagationHeadersFactory(AbstractCompositeAuthenticationProvider compositeProvider,
+ protected AbstractAuthenticationPropagationHeadersFactory(CompositeAuthenticationProvider compositeProvider,
OpenApiGeneratorConfig generatorConfig,
HeadersProvider headersProvider) {
this.compositeProvider = compositeProvider;
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java
index e949fb3f..03a55f6e 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java
@@ -3,6 +3,7 @@
import static io.quarkiverse.openapi.generator.AuthConfig.TOKEN_PROPAGATION;
import java.io.IOException;
+import java.util.List;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.core.Cookie;
@@ -12,7 +13,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
+import io.quarkiverse.openapi.generator.AuthConfig;
import io.quarkiverse.openapi.generator.OpenApiGeneratorException;
/**
@@ -30,9 +31,8 @@ public class ApiKeyAuthenticationProvider extends AbstractAuthProvider {
public ApiKeyAuthenticationProvider(final String openApiSpecId, final String name, final ApiKeyIn apiKeyIn,
final String apiKeyName,
- final OpenApiGeneratorConfig generatorConfig) {
- super(generatorConfig);
- init(name, openApiSpecId);
+ final AuthConfig authConfig, List operations) {
+ super(authConfig, name, openApiSpecId, operations);
this.apiKeyIn = apiKeyIn;
this.apiKeyName = apiKeyName;
validateConfig();
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AuthProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AuthProvider.java
index f3b00ca6..fe00447e 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AuthProvider.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AuthProvider.java
@@ -19,6 +19,4 @@ public interface AuthProvider extends ClientRequestFilter {
List operationsToFilter();
- AuthProvider addOperation(OperationAuthInfo operationAuthInfo);
-
}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BasicAuthenticationProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BasicAuthenticationProvider.java
index 5f9742e5..219828b3 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BasicAuthenticationProvider.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BasicAuthenticationProvider.java
@@ -3,11 +3,12 @@
import static io.quarkiverse.openapi.generator.AuthConfig.TOKEN_PROPAGATION;
import java.io.IOException;
+import java.util.List;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.core.HttpHeaders;
-import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
+import io.quarkiverse.openapi.generator.AuthConfig;
import io.quarkiverse.openapi.generator.OpenApiGeneratorException;
/**
@@ -20,9 +21,9 @@ public class BasicAuthenticationProvider extends AbstractAuthProvider {
static final String USER_NAME = "username";
static final String PASSWORD = "password";
- public BasicAuthenticationProvider(final String openApiSpecId, String name, final OpenApiGeneratorConfig generatorConfig) {
- super(generatorConfig);
- init(name, openApiSpecId);
+ public BasicAuthenticationProvider(final String openApiSpecId, String name, final AuthConfig authConfig,
+ List operations) {
+ super(authConfig, name, openApiSpecId, operations);
validateConfig();
}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BearerAuthenticationProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BearerAuthenticationProvider.java
index d2145482..0e80ab2a 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BearerAuthenticationProvider.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/BearerAuthenticationProvider.java
@@ -1,11 +1,12 @@
package io.quarkiverse.openapi.generator.providers;
import java.io.IOException;
+import java.util.List;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.core.HttpHeaders;
-import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
+import io.quarkiverse.openapi.generator.AuthConfig;
/**
* Provides bearer token authentication or any other valid scheme.
@@ -19,9 +20,8 @@ public class BearerAuthenticationProvider extends AbstractAuthProvider {
private final String scheme;
public BearerAuthenticationProvider(final String openApiSpecId, final String name, final String scheme,
- final OpenApiGeneratorConfig generatorConfig) {
- super(generatorConfig);
- init(name, openApiSpecId);
+ final AuthConfig authConfig, List operations) {
+ super(authConfig, name, openApiSpecId, operations);
this.scheme = scheme;
}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractCompositeAuthenticationProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CompositeAuthenticationProvider.java
similarity index 86%
rename from client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractCompositeAuthenticationProvider.java
rename to client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CompositeAuthenticationProvider.java
index a7ce09ff..3df16cb1 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/AbstractCompositeAuthenticationProvider.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CompositeAuthenticationProvider.java
@@ -3,7 +3,6 @@
import static io.quarkiverse.openapi.generator.providers.AbstractAuthenticationPropagationHeadersFactory.propagationHeaderNamePrefix;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -17,12 +16,12 @@
* Composition of supported {@link ClientRequestFilter} defined by a given OpenAPI interface.
* This class is used as the base class of generated code.
*/
-public abstract class AbstractCompositeAuthenticationProvider implements ClientRequestFilter {
+public class CompositeAuthenticationProvider implements ClientRequestFilter {
- private final List authProviders = new ArrayList<>();
+ private final List authProviders;
- public final void addAuthenticationProvider(final AuthProvider authProvider) {
- this.authProviders.add(authProvider);
+ public CompositeAuthenticationProvider(List authProviders) {
+ this.authProviders = List.copyOf(authProviders);
}
public final List getAuthenticationProviders() {
@@ -30,7 +29,7 @@ public final List getAuthenticationProviders() {
}
@Override
- public final void filter(ClientRequestContext requestContext) throws IOException {
+ public void filter(ClientRequestContext requestContext) throws IOException {
Set removableHeaderPrefix = new HashSet<>();
for (AuthProvider authProvider : authProviders) {
if (authProvider instanceof AbstractAuthProvider) {
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OAuth2AuthenticationProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OAuth2AuthenticationProvider.java
index 2a8915b1..ff5368ce 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OAuth2AuthenticationProvider.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OAuth2AuthenticationProvider.java
@@ -3,6 +3,7 @@
import static io.quarkiverse.openapi.generator.AuthConfig.TOKEN_PROPAGATION;
import java.io.IOException;
+import java.util.List;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.core.HttpHeaders;
@@ -10,31 +11,19 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig;
+import io.quarkiverse.openapi.generator.AuthConfig;
import io.quarkus.oidc.common.runtime.OidcConstants;
-@jakarta.annotation.Priority(jakarta.ws.rs.Priorities.AUTHENTICATION)
-@jakarta.enterprise.context.Dependent
public class OAuth2AuthenticationProvider extends AbstractAuthProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(OAuth2AuthenticationProvider.class);
- private OidcClientRequestFilterDelegate delegate;
+ private final OidcClientRequestFilterDelegate delegate;
- @SuppressWarnings("unused")
- OAuth2AuthenticationProvider() {
- // Required by CDI. Not supposed to be used.
- delegate = null;
- }
-
- @jakarta.inject.Inject
- public OAuth2AuthenticationProvider(final OpenApiGeneratorConfig generatorConfig) {
- super(generatorConfig);
- }
-
- public void init(String name, String openApiSpecId, OidcClientRequestFilterDelegate delegate) {
+ public OAuth2AuthenticationProvider(final AuthConfig authConfig, String name,
+ String openApiSpecId, OidcClientRequestFilterDelegate delegate, List operations) {
+ super(authConfig, name, openApiSpecId, operations);
this.delegate = delegate;
- super.init(name, openApiSpecId);
validateConfig();
}
diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OperationAuthInfo.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OperationAuthInfo.java
index 20e429b1..ec79df46 100644
--- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OperationAuthInfo.java
+++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/OperationAuthInfo.java
@@ -12,6 +12,19 @@ public final class OperationAuthInfo {
public OperationAuthInfo() {
}
+ public void setOperationId(final String operationId) {
+ this.operationId = operationId;
+ }
+
+ public void setPath(final String path) {
+ this.pathMatcher = new UrlPatternMatcher(path);
+ this.path = path;
+ }
+
+ public void setHttpMethod(final String method) {
+ this.httpMethod = method;
+ }
+
public String getHttpMethod() {
return httpMethod;
}
diff --git a/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/AbstractAuthenticationProviderTest.java b/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/AbstractOpenApiSpecProviderTest.java
similarity index 93%
rename from client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/AbstractAuthenticationProviderTest.java
rename to client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/AbstractOpenApiSpecProviderTest.java
index dc5f8958..2387cff6 100644
--- a/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/AbstractAuthenticationProviderTest.java
+++ b/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/AbstractOpenApiSpecProviderTest.java
@@ -21,7 +21,7 @@
import io.quarkiverse.openapi.generator.SpecItemConfig;
@ExtendWith(MockitoExtension.class)
-abstract class AbstractAuthenticationProviderTest {
+abstract class AbstractOpenApiSpecProviderTest {
protected static final String OPEN_API_FILE_SPEC_ID = "open_api_file_spec_id_json";
protected static final String AUTH_SCHEME_NAME = "auth_scheme_name";
@@ -40,11 +40,11 @@ abstract class AbstractAuthenticationProviderTest {
+class ApiKeyOpenApiSpecProviderTest extends AbstractOpenApiSpecProviderTest {
private static final String API_KEY_NAME = "API_KEY_NAME";
private static final String API_KEY_VALUE = "API_KEY_VALUE";
@@ -42,9 +42,9 @@ protected void createConfiguration() {
@Override
protected ApiKeyAuthenticationProvider createProvider(String openApiSpecId, String authSchemeName,
- OpenApiGeneratorConfig openApiGeneratorConfig) {
+ AuthConfig authConfig) {
return new ApiKeyAuthenticationProvider(openApiSpecId, authSchemeName, ApiKeyIn.header, API_KEY_NAME,
- openApiGeneratorConfig);
+ authConfig, List.of());
}
@Test
@@ -82,7 +82,7 @@ void filterHeaderCase() throws IOException {
void filterQueryCase() throws IOException {
doReturn(INVOKED_URI).when(requestContext).getUri();
provider = new ApiKeyAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, ApiKeyIn.query, API_KEY_NAME,
- generatorConfig);
+ authConfig, List.of());
provider.filter(requestContext);
verify(requestContext).setUri(uriCaptor.capture());
assertThat(uriCaptor.getValue())
@@ -95,7 +95,7 @@ void filterCookieCaseEmpty() throws IOException {
final MultivaluedMap headers = new MultivaluedTreeMap<>();
doReturn(headers).when(requestContext).getHeaders();
provider = new ApiKeyAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, ApiKeyIn.cookie, API_KEY_NAME,
- generatorConfig);
+ authConfig, List.of());
provider.filter(requestContext);
final List