From b004757ab0a2689c20d4965012b74cf0d0b8c05a Mon Sep 17 00:00:00 2001 From: gabriel-farache Date: Fri, 6 Jun 2025 15:07:45 +0200 Subject: [PATCH 1/8] Fix #1127 - Use CredentialProvider in OAuth2 provider (#1126) * Use CredentialProvider in OAUTH2 provider and update data structure for CrendentialProvider Signed-off-by: gabriel-farache * Fix Custom auth provider doc Signed-off-by: gabriel-farache --------- Signed-off-by: gabriel-farache --- .../deployment/GeneratorProcessor.java | 1 + .../integration-tests/auth-provider/pom.xml | 124 ++++++++++++++++ .../it/auth/TokenServerResource.java | 50 +++++++ .../provider/CustomCredentialsProvider.java | 27 ++++ .../main/openapi/token-external-service1.yaml | 19 +++ .../main/openapi/token-external-service2.yaml | 23 +++ .../main/openapi/token-external-service3.yaml | 19 +++ .../main/openapi/token-external-service5.yaml | 23 +++ .../src/main/resources/application.properties | 42 ++++++ .../it/auth/KeycloakServiceMock.java | 82 +++++++++++ .../it/auth/TokenExternalServicesMock.java | 72 ++++++++++ ...TokenWithCustomCredentialProviderTest.java | 35 +++++ .../it/creds/CustomCredentialsProvider.java | 3 +- client/integration-tests/pom.xml | 1 + .../it/security/KeycloakServiceMock.java | 37 ++--- client/oidc/pom.xml | 25 ++++ ...lassicOidcClientRequestFilterDelegate.java | 3 +- .../OAuth2AuthenticationProvider.java | 40 ++++-- .../OAuth2AuthenticationProviderTest.java | 124 ++++++++++++++++ ...ctiveOAuth2AuthenticationProviderTest.java | 136 ++++++++++++++++++ .../providers/AbstractAuthProvider.java | 40 ++++-- .../ApiKeyAuthenticationProvider.java | 6 +- .../BasicAuthenticationProvider.java | 12 +- .../BearerAuthenticationProvider.java | 6 +- .../providers/ConfigCredentialsProvider.java | 32 +++-- .../providers/CredentialsProvider.java | 84 +++++++++-- .../pages/includes/custom-auth-provider.adoc | 2 +- 27 files changed, 993 insertions(+), 75 deletions(-) create mode 100644 client/integration-tests/auth-provider/pom.xml create mode 100644 client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/TokenServerResource.java create mode 100644 client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java create mode 100644 client/integration-tests/auth-provider/src/main/openapi/token-external-service1.yaml create mode 100644 client/integration-tests/auth-provider/src/main/openapi/token-external-service2.yaml create mode 100644 client/integration-tests/auth-provider/src/main/openapi/token-external-service3.yaml create mode 100644 client/integration-tests/auth-provider/src/main/openapi/token-external-service5.yaml create mode 100644 client/integration-tests/auth-provider/src/main/resources/application.properties create mode 100644 client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/KeycloakServiceMock.java create mode 100644 client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenExternalServicesMock.java create mode 100644 client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenWithCustomCredentialProviderTest.java create mode 100644 client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java create mode 100644 client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java 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 index 6538f9ce4..fa9e3faa9 100644 --- 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 @@ -174,6 +174,7 @@ void produceOauthAuthentication(CombinedIndexBuildItem beanArchiveBuildItem, .annotation(OpenApiSpec.class) .addValue("openApiSpecId", openApiSpecId) .done() + .addInjectionPoint(ClassType.create(DotName.createSimple(CredentialsProvider.class))) .addInjectionPoint(ClassType.create(OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate.class), AnnotationInstance.builder(OidcClient.class).add("name", sanitizeAuthName(name)).build()) .addInjectionPoint(ClassType.create(DotName.createSimple(CredentialsProvider.class))) diff --git a/client/integration-tests/auth-provider/pom.xml b/client/integration-tests/auth-provider/pom.xml new file mode 100644 index 000000000..8a0bddcc2 --- /dev/null +++ b/client/integration-tests/auth-provider/pom.xml @@ -0,0 +1,124 @@ + + + + quarkus-openapi-generator-integration-tests + io.quarkiverse.openapi.generator + 3.0.0-SNAPSHOT + + 4.0.0 + + quarkus-openapi-generator-it-auth-provider + Quarkus - OpenAPI Generator - Integration Tests - Client - Auth Provider + A few use cases that relies on authentication provider use cases with the OpenAPI Generator + + + + io.quarkiverse.openapi.generator + quarkus-openapi-generator + + + io.quarkiverse.openapi.generator + quarkus-openapi-generator-oidc + + + io.quarkus + quarkus-junit5 + test + + + org.wiremock + wiremock + test + + + io.rest-assured + rest-assured + test + + + + + + + io.quarkus + quarkus-maven-plugin + true + + + + build + generate-code + generate-code-tests + + + + + + + + + native-image + + + native + + + + + + maven-surefire-plugin + + ${native.surefire.skip} + + + + maven-failsafe-plugin + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + + resteasy-reactive + + + io.quarkus + quarkus-rest-client-oidc-filter + + + + + resteasy-classic + + true + + + + io.quarkus + quarkus-resteasy-client-oidc-filter + + + io.quarkus + quarkus-resteasy-multipart + + + + + \ No newline at end of file diff --git a/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/TokenServerResource.java b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/TokenServerResource.java new file mode 100644 index 000000000..9c3ae7e57 --- /dev/null +++ b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/TokenServerResource.java @@ -0,0 +1,50 @@ +package io.quarkiverse.openapi.generator.it.auth; + +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; + +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/token_server") +public class TokenServerResource { + + @RestClient + org.acme.externalservice1.api.DefaultApi defaultApi1; + + @RestClient + org.acme.externalservice2.api.DefaultApi defaultApi2; + + @RestClient + org.acme.externalservice3.api.DefaultApi defaultApi3; + + @RestClient + org.acme.externalservice5.api.DefaultApi defaultApi5; + + @POST + @Path("service1") + public String service1() { + defaultApi1.executeQuery1(); + return "hello"; + } + + @POST + @Path("service2") + public String service2() { + defaultApi2.executeQuery2(); + return "hello"; + } + + @POST + @Path("service3") + public String service3() { + defaultApi3.executeQuery3(); + return "hello"; + } + + @POST + @Path("service5") + public String service5() { + defaultApi5.executeQuery5(); + return "hello"; + } +} diff --git a/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java new file mode 100644 index 000000000..e2bc1b8af --- /dev/null +++ b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java @@ -0,0 +1,27 @@ +package io.quarkiverse.openapi.generator.it.auth.provider; + +import jakarta.annotation.Priority; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Alternative; +import jakarta.enterprise.inject.Specializes; + +import io.quarkiverse.openapi.generator.providers.ConfigCredentialsProvider; + +@Dependent +@Alternative +@Specializes +@Priority(200) +public class CustomCredentialsProvider extends ConfigCredentialsProvider { + public CustomCredentialsProvider() { + } + + @Override + public String getBearerToken(CredentialsContext input) { + return super.getBearerToken(input) + "_TEST"; + } + + @Override + public String getOauth2BearerToken(CredentialsContext input) { + return super.getOauth2BearerToken(input) + "_TEST"; + } +} diff --git a/client/integration-tests/auth-provider/src/main/openapi/token-external-service1.yaml b/client/integration-tests/auth-provider/src/main/openapi/token-external-service1.yaml new file mode 100644 index 000000000..dd18964c1 --- /dev/null +++ b/client/integration-tests/auth-provider/src/main/openapi/token-external-service1.yaml @@ -0,0 +1,19 @@ +--- +openapi: 3.0.3 +info: + title: token-external-service1 API + version: 3.0.0-SNAPSHOT +paths: + /token-external-service1/executeQuery1: + post: + operationId: executeQuery1 + responses: + "200": + description: OK + security: + - service1-http-bearer: [] +components: + securitySchemes: + service1-http-bearer: + type: http + scheme: bearer \ No newline at end of file diff --git a/client/integration-tests/auth-provider/src/main/openapi/token-external-service2.yaml b/client/integration-tests/auth-provider/src/main/openapi/token-external-service2.yaml new file mode 100644 index 000000000..726200831 --- /dev/null +++ b/client/integration-tests/auth-provider/src/main/openapi/token-external-service2.yaml @@ -0,0 +1,23 @@ +--- +openapi: 3.0.3 +info: + title: token-external-service2 API + version: 3.0.0-SNAPSHOT +paths: + /token-external-service2/executeQuery2: + post: + operationId: executeQuery2 + responses: + "200": + description: OK + security: + - service2-oauth2: [] +components: + securitySchemes: + service2-oauth2: + type: oauth2 + flows: + clientCredentials: + authorizationUrl: https://example.com/oauth + tokenUrl: https://example.com/oauth/token + scopes: {} \ No newline at end of file diff --git a/client/integration-tests/auth-provider/src/main/openapi/token-external-service3.yaml b/client/integration-tests/auth-provider/src/main/openapi/token-external-service3.yaml new file mode 100644 index 000000000..981daef3c --- /dev/null +++ b/client/integration-tests/auth-provider/src/main/openapi/token-external-service3.yaml @@ -0,0 +1,19 @@ +--- +openapi: 3.0.3 +info: + title: token-external-service3 API + version: 3.0.0-SNAPSHOT +paths: + /token-external-service3/executeQuery3: + post: + operationId: executeQuery3 + responses: + "200": + description: OK + security: + - service3-http-bearer: [] +components: + securitySchemes: + service3-http-bearer: + type: http + scheme: bearer \ No newline at end of file diff --git a/client/integration-tests/auth-provider/src/main/openapi/token-external-service5.yaml b/client/integration-tests/auth-provider/src/main/openapi/token-external-service5.yaml new file mode 100644 index 000000000..4490dcf00 --- /dev/null +++ b/client/integration-tests/auth-provider/src/main/openapi/token-external-service5.yaml @@ -0,0 +1,23 @@ +--- +openapi: 3.0.3 +info: + title: token-external-service5 API + version: 3.0.0-SNAPSHOT +paths: + /token-external-service5/executeQuery5: + post: + operationId: executeQuery5 + responses: + "200": + description: OK + security: + - service5-oauth2: [] +components: + securitySchemes: + service5-oauth2: + type: oauth2 + flows: + clientCredentials: + authorizationUrl: https://example.com/oauth + tokenUrl: https://example.com/oauth/token + scopes: {} \ No newline at end of file diff --git a/client/integration-tests/auth-provider/src/main/resources/application.properties b/client/integration-tests/auth-provider/src/main/resources/application.properties new file mode 100644 index 000000000..eeed16b8a --- /dev/null +++ b/client/integration-tests/auth-provider/src/main/resources/application.properties @@ -0,0 +1,42 @@ +# Note: The property value is the name of an existing securityScheme in the spec file +quarkus.openapi-generator.codegen.default-security-scheme=app_id + +#Token service +quarkus.openapi-generator.codegen.spec.token_external_service1_yaml.base-package=org.acme.externalservice1 +quarkus.openapi-generator.codegen.spec.token_external_service2_yaml.base-package=org.acme.externalservice2 +quarkus.openapi-generator.codegen.spec.token_external_service3_yaml.base-package=org.acme.externalservice3 +quarkus.openapi-generator.codegen.spec.token_external_service5_yaml.base-package=org.acme.externalservice5 + +quarkus.rest-client.token_external_service1_yaml.url=${propagation-external-service-mock.url} +quarkus.rest-client.token_external_service2_yaml.url=${propagation-external-service-mock.url} +quarkus.rest-client.token_external_service3_yaml.url=${propagation-external-service-mock.url} +quarkus.rest-client.token_external_service5_yaml.url=${propagation-external-service-mock.url} + +# default propagation for token_external_service1 invocation +quarkus.openapi-generator.token_external_service1_yaml.auth.service1_http_bearer.token-propagation=true +# default propagation for token_external_service2 invocation +quarkus.openapi-generator.token_external_service2_yaml.auth.service2_oauth2.token-propagation=true + +quarkus.openapi-generator.token_external_service3_yaml.auth.service3_http_bearer.bearer-token=BEARER_TOKEN + +# Oidc clients for the services that has oauth2 security. +# Oidc client used by the token_external_service2 +quarkus.oidc-client.service2_oauth2.auth-server-url=${keycloak.mock.service.url} +quarkus.oidc-client.service2_oauth2.token-path=${keycloak.mock.service.token-path} +quarkus.oidc-client.service2_oauth2.discovery-enabled=false +quarkus.oidc-client.service2_oauth2.client-id=kogito-app +quarkus.oidc-client.service2_oauth2.grant.type=client +quarkus.oidc-client.service2_oauth2.credentials.client-secret.method=basic +quarkus.oidc-client.service2_oauth2.credentials.client-secret.value=secret + + +# Oidc client used by the token_external_service5 +quarkus.oidc-client.service5_oauth2.auth-server-url=${keycloak.mock.service.url} +quarkus.oidc-client.service5_oauth2.token-path=${keycloak.mock.service.token-path} +quarkus.oidc-client.service5_oauth2.discovery-enabled=false +quarkus.oidc-client.service5_oauth2.client-id=kogito-app +quarkus.oidc-client.service5_oauth2.grant.type=client +quarkus.oidc-client.service5_oauth2.credentials.client-secret.method=basic +quarkus.oidc-client.service5_oauth2.credentials.client-secret.value=secret + +quarkus.keycloak.devservices.enabled=false \ No newline at end of file diff --git a/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/KeycloakServiceMock.java b/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/KeycloakServiceMock.java new file mode 100644 index 000000000..477d7d253 --- /dev/null +++ b/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/KeycloakServiceMock.java @@ -0,0 +1,82 @@ +package io.quarkiverse.openapi.generator.it.auth; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE; +import static jakarta.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; + +import java.util.HashMap; +import java.util.Map; + +import com.github.tomakehurst.wiremock.WireMockServer; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; + +/** + * Lightweight Keycloak mock to use when an OidcClient is required, and we don't want/need to start a full Keycloak + * container as part of the tests, etc. Keep the things simple. + */ +public class KeycloakServiceMock implements QuarkusTestResourceLifecycleManager { + + public static final String KEY_CLOAK_SERVICE_URL = "keycloak.mock.service.url"; + public static final String KEY_CLOAK_SERVICE_TOKEN_PATH = "keycloak.mock.service.token-path"; + public static final String REALM = "kogito-tests"; + public static final String KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE = "/realms/" + REALM + "/protocol/openid-connect/token"; + public static final String CLIENT_ID = "kogito-app"; + public static final String SECRET = "secret"; + public static final String KEYCLOAK_ACCESS_TOKEN = "KEYCLOAK_ACCESS_TOKEN"; + public static final String KEYCLOAK_REFRESH_TOKEN = "KEYCLOAK_REFRESH_TOKEN"; + public static final String KEYCLOAK_SESSION_STATE = "KEYCLOAK_SESSION_STATE"; + + public static final String AUTH_REQUEST_BODY = "grant_type=client_credentials"; + + private static final ThreadLocal wireMockServer = new ThreadLocal<>(); + + @Override + public Map start() { + wireMockServer.set(new WireMockServer(options().dynamicPort())); + wireMockServer.get().start(); + configureFor(wireMockServer.get().port()); + + stubFor(post(KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE) + .withHeader(CONTENT_TYPE, equalTo(APPLICATION_FORM_URLENCODED)) + .withBasicAuth(CLIENT_ID, SECRET) + .withRequestBody(equalTo(AUTH_REQUEST_BODY)) + .willReturn(aResponse() + .withHeader(CONTENT_TYPE, APPLICATION_JSON) + .withBody(getTokenResult()))); + + Map properties = new HashMap<>(); + properties.put(KEY_CLOAK_SERVICE_URL, wireMockServer.get().baseUrl()); + properties.put(KEY_CLOAK_SERVICE_TOKEN_PATH, KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE); + return properties; + } + + private static String getTokenResult() { + return """ + { + "access_token": "%s", + "expires_in": 300, + "refresh_expires_in": 1800, + "refresh_token": "%s", + "token_type": "bearer", + "not-before-policy": 0, + "session_state": "%s", + "scope": "email profile" + } + """.formatted(KEYCLOAK_ACCESS_TOKEN, KEYCLOAK_REFRESH_TOKEN, KEYCLOAK_SESSION_STATE); + } + + @Override + public void stop() { + if (wireMockServer.get() != null) { + wireMockServer.get().stop(); + wireMockServer.remove(); + } + } +} diff --git a/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenExternalServicesMock.java b/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenExternalServicesMock.java new file mode 100644 index 000000000..7a4545218 --- /dev/null +++ b/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenExternalServicesMock.java @@ -0,0 +1,72 @@ +package io.quarkiverse.openapi.generator.it.auth; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static io.quarkiverse.openapi.generator.it.auth.KeycloakServiceMock.KEYCLOAK_ACCESS_TOKEN; +import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; + +import java.util.Map; + +import jakarta.ws.rs.core.HttpHeaders; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.github.tomakehurst.wiremock.WireMockServer; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; + +public class TokenExternalServicesMock implements QuarkusTestResourceLifecycleManager { + + public static final String AUTHORIZATION_TOKEN = "AUTHORIZATION_TOKEN"; + public static final String SERVICE3_AUTHORIZATION_TOKEN = "BEARER_TOKEN"; + public static final String TOKEN_EXTERNAL_SERVICE_MOCK_URL = "propagation-external-service-mock.url"; + private static final String BEARER = "Bearer "; + private static final Logger LOGGER = LoggerFactory.getLogger(TokenExternalServicesMock.class); + private WireMockServer wireMockServer; + + private static void stubForExternalService(String tokenPropagationExternalServiceUrl, String authorizationToken) { + stubFor(post(tokenPropagationExternalServiceUrl) + .withHeader(HttpHeaders.AUTHORIZATION, equalTo(BEARER + authorizationToken)) + .willReturn(aResponse() + .withHeader(CONTENT_TYPE, APPLICATION_JSON) + .withBody("{}"))); + } + + @Override + public Map start() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + configureFor(wireMockServer.port()); + LOGGER.info("Mocked Server started at {}", wireMockServer.baseUrl()); + + // stub the token-external-service1 invocation with the expected token + stubForExternalService("/token-external-service1/executeQuery1", AUTHORIZATION_TOKEN); + + // stub the token-external-service2 invocation with the expected token + stubForExternalService("/token-external-service2/executeQuery2", AUTHORIZATION_TOKEN); + + // stub the token-external-service3 invocation with the expected token taken from the + // application.properties and overridden by the custom credential provider + stubForExternalService("/token-external-service3/executeQuery3", SERVICE3_AUTHORIZATION_TOKEN + "_TEST"); + + // stub the token-external-service5 invocation with the expected token, no propagation is produced + // in this case but the service must receive the token provided by Keycloak since it has oauth2 security + // configured. The token will be overridden by the custom credential provider + stubForExternalService("/token-external-service5/executeQuery5", KEYCLOAK_ACCESS_TOKEN + "_TEST"); + + return Map.of(TOKEN_EXTERNAL_SERVICE_MOCK_URL, wireMockServer.baseUrl()); + } + + @Override + public void stop() { + if (wireMockServer != null) { + wireMockServer.stop(); + } + } +} diff --git a/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenWithCustomCredentialProviderTest.java b/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenWithCustomCredentialProviderTest.java new file mode 100644 index 000000000..9fd525475 --- /dev/null +++ b/client/integration-tests/auth-provider/src/test/java/io/quarkiverse/openapi/generator/it/auth/TokenWithCustomCredentialProviderTest.java @@ -0,0 +1,35 @@ +package io.quarkiverse.openapi.generator.it.auth; + +import static io.quarkiverse.openapi.generator.it.auth.TokenExternalServicesMock.AUTHORIZATION_TOKEN; +import static io.restassured.RestAssured.given; + +import java.util.Map; + +import jakarta.ws.rs.core.HttpHeaders; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTestResource(TokenExternalServicesMock.class) +@QuarkusTestResource(KeycloakServiceMock.class) +@QuarkusTest +// Enabled only for RESTEasy Classic while https://github.com/quarkiverse/quarkus-openapi-generator/issues/434 is not fixed +@Tag("resteasy-classic") +class TokenWithCustomCredentialProviderTest { + + @ParameterizedTest + @ValueSource(strings = { "service1", "service2", "service3", "service5" }) + void testService(String service) { + Map headers = Map.of(HttpHeaders.AUTHORIZATION, AUTHORIZATION_TOKEN); + + given() + .headers(headers) + .post("/token_server/" + service) + .then() + .statusCode(200); + } +} diff --git a/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java b/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java index 0ac9e2282..8bbc39b68 100644 --- a/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java +++ b/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java @@ -3,7 +3,6 @@ import jakarta.annotation.Priority; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Alternative; -import jakarta.ws.rs.client.ClientRequestContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,7 +18,7 @@ public class CustomCredentialsProvider extends ConfigCredentialsProvider { public static String TOKEN = "FIXED_TEST_TOKEN"; @Override - public String getBearerToken(ClientRequestContext requestContext, String openApiSpecId, String authName) { + public String getBearerToken(CredentialsContext input) { LOGGER.info("========> getBearerToken from CustomCredentialsProvider"); return TOKEN; } diff --git a/client/integration-tests/pom.xml b/client/integration-tests/pom.xml index 362a3a38c..661f2ec90 100644 --- a/client/integration-tests/pom.xml +++ b/client/integration-tests/pom.xml @@ -12,6 +12,7 @@ pom additional-properties + auth-provider array-enum bean-validation beanparam diff --git a/client/integration-tests/security/src/test/java/io/quarkiverse/openapi/generator/it/security/KeycloakServiceMock.java b/client/integration-tests/security/src/test/java/io/quarkiverse/openapi/generator/it/security/KeycloakServiceMock.java index 06fd6aa57..264b34bea 100644 --- a/client/integration-tests/security/src/test/java/io/quarkiverse/openapi/generator/it/security/KeycloakServiceMock.java +++ b/client/integration-tests/security/src/test/java/io/quarkiverse/openapi/generator/it/security/KeycloakServiceMock.java @@ -35,13 +35,13 @@ public class KeycloakServiceMock implements QuarkusTestResourceLifecycleManager public static final String AUTH_REQUEST_BODY = "grant_type=client_credentials"; - private WireMockServer wireMockServer; + private static final ThreadLocal wireMockServer = new ThreadLocal<>(); @Override public Map start() { - wireMockServer = new WireMockServer(options().dynamicPort()); - wireMockServer.start(); - configureFor(wireMockServer.port()); + wireMockServer.set(new WireMockServer(options().dynamicPort())); + wireMockServer.get().start(); + configureFor(wireMockServer.get().port()); stubFor(post(KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE) .withHeader(CONTENT_TYPE, equalTo(APPLICATION_FORM_URLENCODED)) @@ -52,28 +52,31 @@ public Map start() { .withBody(getTokenResult()))); Map properties = new HashMap<>(); - properties.put(KEY_CLOAK_SERVICE_URL, wireMockServer.baseUrl()); + properties.put(KEY_CLOAK_SERVICE_URL, wireMockServer.get().baseUrl()); properties.put(KEY_CLOAK_SERVICE_TOKEN_PATH, KEY_CLOAK_SERVICE_TOKEN_PATH_VALUE); return properties; } private static String getTokenResult() { - return "{\n" + - " \"access_token\": \"" + KEYCLOAK_ACCESS_TOKEN + "\",\n" + - " \"expires_in\": 300,\n" + - " \"refresh_expires_in\": 1800,\n" + - " \"refresh_token\": \"" + KEYCLOAK_REFRESH_TOKEN + "\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"not-before-policy\": 0,\n" + - " \"session_state\": \"" + KEYCLOAK_SESSION_STATE + "\",\n" + - " \"scope\": \"email profile\"\n" + - "}"; + return """ + { + "access_token": "%s", + "expires_in": 300, + "refresh_expires_in": 1800, + "refresh_token": "%s", + "token_type": "bearer", + "not-before-policy": 0, + "session_state": "%s", + "scope": "email profile" + } + """.formatted(KEYCLOAK_ACCESS_TOKEN, KEYCLOAK_REFRESH_TOKEN, KEYCLOAK_SESSION_STATE); } @Override public void stop() { - if (wireMockServer != null) { - wireMockServer.stop(); + if (wireMockServer.get() != null) { + wireMockServer.get().stop(); + wireMockServer.remove(); } } } diff --git a/client/oidc/pom.xml b/client/oidc/pom.xml index 078a5ea01..3da32f6bb 100644 --- a/client/oidc/pom.xml +++ b/client/oidc/pom.xml @@ -27,6 +27,31 @@ quarkus-resteasy-client-oidc-filter provided + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + io.quarkus + quarkus-junit5 + test + + + org.jboss.resteasy + resteasy-core + test + \ No newline at end of file diff --git a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/ClassicOidcClientRequestFilterDelegate.java b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/ClassicOidcClientRequestFilterDelegate.java index f37895c8a..677ee5b48 100644 --- a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/ClassicOidcClientRequestFilterDelegate.java +++ b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/ClassicOidcClientRequestFilterDelegate.java @@ -7,6 +7,7 @@ import jakarta.ws.rs.Priorities; import jakarta.ws.rs.client.ClientRequestContext; import jakarta.ws.rs.client.ClientRequestFilter; +import jakarta.ws.rs.core.HttpHeaders; import org.jboss.logging.Logger; @@ -41,7 +42,7 @@ protected java.util.Optional clientId() { public void filter(ClientRequestContext requestContext) throws IOException { try { String accessToken = this.getAccessToken(); - requestContext.getHeaders().add("Authorization", "Bearer " + accessToken); + requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); } catch (DisabledOidcClientException ex) { LOG.debug("Client is disabled, acquiring and propagating the token is not necessary"); } catch (RuntimeException ex) { diff --git a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java index 4b5a9ea39..541d47220 100644 --- a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java +++ b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java @@ -6,14 +6,16 @@ import java.util.List; import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.core.HttpHeaders; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.quarkiverse.openapi.generator.providers.AbstractAuthProvider; +import io.quarkiverse.openapi.generator.providers.AuthUtils; +import io.quarkiverse.openapi.generator.providers.ConfigCredentialsProvider; import io.quarkiverse.openapi.generator.providers.CredentialsProvider; import io.quarkiverse.openapi.generator.providers.OperationAuthInfo; -import io.quarkus.oidc.common.runtime.OidcConstants; public class OAuth2AuthenticationProvider extends AbstractAuthProvider { @@ -22,32 +24,44 @@ public class OAuth2AuthenticationProvider extends AbstractAuthProvider { private final OidcClientRequestFilterDelegate delegate; public OAuth2AuthenticationProvider(String name, - String openApiSpecId, OidcClientRequestFilterDelegate delegate, List operations, - CredentialsProvider credentialsProvider) { + String openApiSpecId, OidcClientRequestFilterDelegate delegate, List operations, + CredentialsProvider credentialsProvider) { super(name, openApiSpecId, operations, credentialsProvider); this.delegate = delegate; validateConfig(); } + public OAuth2AuthenticationProvider(String name, + String openApiSpecId, OidcClientRequestFilterDelegate delegate, List operations) { + this(name, openApiSpecId, delegate, operations, new ConfigCredentialsProvider()); + } + @Override public void filter(ClientRequestContext requestContext) throws IOException { - if (isTokenPropagation()) { - String bearerToken = sanitizeBearerToken(getTokenForPropagation(requestContext.getHeaders())); - if (!isEmptyOrBlank(bearerToken)) { - addAuthorizationHeader(requestContext.getHeaders(), OidcConstants.BEARER_SCHEME + " " + bearerToken); - } else { - LOGGER.debug("No oauth2 bearer token was found to propagate for the security scheme: {}." + - " You must verify that the request header: {} is set.", getName(), getHeaderForPropagation()); - } + String bearerToken; + + if (this.isTokenPropagation()) { + bearerToken = this.getTokenForPropagation(requestContext.getHeaders()); } else { delegate.filter(requestContext); + bearerToken = this.getCredentialsProvider().getOauth2BearerToken(CredentialsProvider.CredentialsContext.builder() + .requestContext(requestContext) + .openApiSpecId(getOpenApiSpecId()) + .authName(getName()) + .build()); + } + + if (bearerToken != null && !bearerToken.isBlank()) { + requestContext.getHeaders().remove(HttpHeaders.AUTHORIZATION); + requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, + AuthUtils.authTokenOrBearer("Bearer", AbstractAuthProvider.sanitizeBearerToken(bearerToken))); } } private void validateConfig() { if (isTokenPropagation()) { LOGGER.warn("Token propagation was enabled for a the oauth2: {} securityScheme in the specification file: {}. " + - "This configuration can be done by using the property: {} and is not necessary a problem if the configuration is intentional.", + "This configuration can be done by using the property: {} and is not necessary a problem if the configuration is intentional.", getName(), getOpenApiSpecId(), getCanonicalAuthConfigPropertyName(TOKEN_PROPAGATION)); } } @@ -55,4 +69,4 @@ private void validateConfig() { public interface OidcClientRequestFilterDelegate { void filter(ClientRequestContext requestContext) throws IOException; } -} +} \ No newline at end of file diff --git a/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java new file mode 100644 index 000000000..8eaa1e2dc --- /dev/null +++ b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java @@ -0,0 +1,124 @@ +package io.quarkiverse.openapi.generator.oidc; + +import static io.quarkiverse.openapi.generator.providers.AbstractAuthenticationPropagationHeadersFactory.propagationHeaderName; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MultivaluedHashMap; +import jakarta.ws.rs.core.MultivaluedMap; + +import org.assertj.core.api.Assertions; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import io.quarkiverse.openapi.generator.AuthConfig; +import io.quarkiverse.openapi.generator.oidc.providers.OAuth2AuthenticationProvider; +import io.quarkus.oidc.client.Tokens; + +@ExtendWith(MockitoExtension.class) +public class OAuth2AuthenticationProviderTest { + private static final String OPEN_API_FILE_SPEC_ID = "open_api_file_spec_id_json"; + private static final String AUTH_SCHEME_NAME = "auth_scheme_name"; + + private static final String ACCESS_TOKEN = "ACCESS_TOKEN"; + + private static final String PROPAGATED_TOKEN = "PROPAGATED_TOKEN"; + + private static final String HEADER_NAME = "HEADER_NAME"; + + @Mock + private ClientRequestContext requestContext; + + private MultivaluedMap headers; + + private ClassicOidcClientRequestFilterDelegate classicDelegate; + + private static final Tokens token = new Tokens(ACCESS_TOKEN, Long.MAX_VALUE, null, "", Long.MAX_VALUE, null, ""); + + private OAuth2AuthenticationProvider provider; + + @BeforeEach + void setUp() { + headers = new MultivaluedHashMap<>(); + Mockito.lenient().doReturn(headers).when(requestContext).getHeaders(); + + classicDelegate = Mockito.mock(ClassicOidcClientRequestFilterDelegate.class); + Mockito.lenient().when(classicDelegate.awaitTokens()).thenReturn(token); + try { + Mockito.lenient().doCallRealMethod().when(classicDelegate).filter(requestContext); + } catch (IOException e) { + throw new RuntimeException(e); + } + provider = createClassicProvider(); + + } + + private OAuth2AuthenticationProvider createClassicProvider() { + return new OAuth2AuthenticationProvider(AUTH_SCHEME_NAME, OPEN_API_FILE_SPEC_ID, classicDelegate, List.of()); + } + + private void assertHeader(MultivaluedMap headers, String headerName, String value) { + Assertions.assertThat(headers.getFirst(headerName)) + .isNotNull() + .isEqualTo(value); + } + + static Stream filterWithPropagationTestValues() { + return Stream.of( + Arguments.of(null, "Bearer " + PROPAGATED_TOKEN), + Arguments.of(HEADER_NAME, "Bearer " + PROPAGATED_TOKEN)); + } + + @Test + void filterClassic() throws IOException { + filter(provider, "Bearer " + ACCESS_TOKEN); + } + + private void filter(OAuth2AuthenticationProvider provider, String expectedAuthorizationHeader) throws IOException { + provider.filter(requestContext); + assertHeader(headers, HttpHeaders.AUTHORIZATION, expectedAuthorizationHeader); + } + + @ParameterizedTest + @MethodSource("filterWithPropagationTestValues") + void filterWithPropagation(String headerName, + String expectedAuthorizationHeader) throws IOException { + String propagatedHeaderName; + if (headerName == null) { + propagatedHeaderName = propagationHeaderName(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, + HttpHeaders.AUTHORIZATION); + } else { + propagatedHeaderName = propagationHeaderName(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, + HEADER_NAME); + } + try (MockedStatic configProviderMocked = Mockito.mockStatic(ConfigProvider.class)) { + Config mockedConfig = Mockito.mock(Config.class); + configProviderMocked.when(ConfigProvider::getConfig).thenReturn(mockedConfig); + + when(mockedConfig.getOptionalValue(provider.getCanonicalAuthConfigPropertyName(AuthConfig.TOKEN_PROPAGATION), + Boolean.class)).thenReturn(Optional.of(true)); + when(mockedConfig.getOptionalValue(provider.getCanonicalAuthConfigPropertyName(AuthConfig.HEADER_NAME), + String.class)).thenReturn(Optional.of(headerName == null ? HttpHeaders.AUTHORIZATION : headerName)); + + headers.putSingle(propagatedHeaderName, PROPAGATED_TOKEN); + filter(provider, expectedAuthorizationHeader); + } + } + +} diff --git a/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java new file mode 100644 index 000000000..68169a3d8 --- /dev/null +++ b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java @@ -0,0 +1,136 @@ +package io.quarkiverse.openapi.generator.oidc; + +import static io.quarkiverse.openapi.generator.providers.AbstractAuthenticationPropagationHeadersFactory.propagationHeaderName; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MultivaluedHashMap; +import jakarta.ws.rs.core.MultivaluedMap; + +import org.assertj.core.api.Assertions; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; +import org.jboss.resteasy.reactive.client.impl.ClientRequestContextImpl; +import org.jboss.resteasy.reactive.client.impl.RestClientRequestContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import io.quarkiverse.openapi.generator.AuthConfig; +import io.quarkiverse.openapi.generator.oidc.providers.OAuth2AuthenticationProvider; +import io.quarkus.oidc.client.Tokens; +import io.smallrye.mutiny.Uni; + +@ExtendWith(MockitoExtension.class) +public class ReactiveOAuth2AuthenticationProviderTest { + private static final String OPEN_API_FILE_SPEC_ID = "open_api_file_spec_id_json"; + private static final String AUTH_SCHEME_NAME = "auth_scheme_name"; + + private static final String ACCESS_TOKEN = "REACTIVE_ACCESS_TOKEN"; + + private static final String PROPAGATED_TOKEN = "PROPAGATED_TOKEN"; + + private static final String HEADER_NAME = "HEADER_NAME"; + @Mock + private ClientRequestContextImpl reactiveRequestContext; + + @Mock + private RestClientRequestContext restClientRequestContext; + private MultivaluedMap headers; + + private ReactiveOidcClientRequestFilterDelegate reactiveDelegate; + private static final Tokens token = new Tokens(ACCESS_TOKEN, Long.MAX_VALUE, null, "", Long.MAX_VALUE, null, ""); + private static final Uni uniToken = Uni.createFrom().item(token); + + private OAuth2AuthenticationProvider provider; + + @BeforeEach + void setUp() { + headers = new MultivaluedHashMap<>(); + Mockito.lenient().doReturn(headers).when(reactiveRequestContext).getHeaders(); + Mockito.lenient().doReturn(restClientRequestContext).when(reactiveRequestContext).getRestClientRequestContext(); + Mockito.lenient().doAnswer(invocationOnMock -> restClientRequestContext.setSuspended(true)) + .when(restClientRequestContext).suspend(); + Mockito.lenient().doAnswer(invocationOnMock -> restClientRequestContext.setSuspended(false)) + .when(restClientRequestContext).resume(); + reactiveDelegate = Mockito.mock(ReactiveOidcClientRequestFilterDelegate.class); + try { + Mockito.lenient().doCallRealMethod().when(reactiveDelegate).filter(Mockito.any(ClientRequestContext.class)); + } catch (IOException e) { + throw new RuntimeException(e); + } + Mockito.lenient().doCallRealMethod().when(reactiveDelegate).filter(reactiveRequestContext); + Mockito.lenient().when(reactiveDelegate.getTokens()).thenReturn(uniToken); + + provider = createReactiveProvider(); + } + + protected OAuth2AuthenticationProvider createReactiveProvider() { + return new OAuth2AuthenticationProvider(AUTH_SCHEME_NAME, OPEN_API_FILE_SPEC_ID, reactiveDelegate, List.of()); + } + + protected void assertHeader(MultivaluedMap headers, String headerName, String value) { + Assertions.assertThat(headers.getFirst(headerName)) + .isNotNull() + .isEqualTo(value); + } + + static Stream filterWithPropagationTestValues() { + return Stream.of( + Arguments.of(null, "Bearer " + PROPAGATED_TOKEN), + Arguments.of(HEADER_NAME, "Bearer " + PROPAGATED_TOKEN)); + } + + @Test + void filterReactive() throws IOException, InterruptedException { + filter(provider, "Bearer " + ACCESS_TOKEN); + } + + private void filter(OAuth2AuthenticationProvider provider, String expectedAuthorizationHeader) + throws IOException, InterruptedException { + provider.filter(reactiveRequestContext); + while (reactiveRequestContext.getRestClientRequestContext().isSuspended()) { + Thread.sleep(1000); + } + assertHeader(headers, HttpHeaders.AUTHORIZATION, expectedAuthorizationHeader); + } + + @ParameterizedTest + @MethodSource("filterWithPropagationTestValues") + void filterWithPropagation(String headerName, + String expectedAuthorizationHeader) throws IOException, InterruptedException { + String propagatedHeaderName; + if (headerName == null) { + propagatedHeaderName = propagationHeaderName(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, + HttpHeaders.AUTHORIZATION); + } else { + propagatedHeaderName = propagationHeaderName(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, + HEADER_NAME); + } + try (MockedStatic configProviderMocked = Mockito.mockStatic(ConfigProvider.class)) { + Config mockedConfig = Mockito.mock(Config.class); + configProviderMocked.when(ConfigProvider::getConfig).thenReturn(mockedConfig); + + when(mockedConfig.getOptionalValue(provider.getCanonicalAuthConfigPropertyName(AuthConfig.TOKEN_PROPAGATION), + Boolean.class)).thenReturn(Optional.of(true)); + when(mockedConfig.getOptionalValue(provider.getCanonicalAuthConfigPropertyName(AuthConfig.HEADER_NAME), + String.class)).thenReturn(Optional.of(headerName == null ? HttpHeaders.AUTHORIZATION : headerName)); + + headers.putSingle(propagatedHeaderName, PROPAGATED_TOKEN); + filter(provider, expectedAuthorizationHeader); + } + } +} 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 ff738a16e..93e910abd 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 @@ -4,7 +4,6 @@ import static io.quarkiverse.openapi.generator.providers.AbstractAuthenticationPropagationHeadersFactory.propagationHeaderName; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -30,7 +29,7 @@ public abstract class AbstractAuthProvider implements AuthProvider { private final List applyToOperations = new ArrayList<>(); protected AbstractAuthProvider(String name, String openApiSpecId, List operations, - CredentialsProvider credentialsProvider) { + CredentialsProvider credentialsProvider) { this.name = name; this.openApiSpecId = openApiSpecId; this.applyToOperations.addAll(operations); @@ -61,18 +60,19 @@ public String getName() { } public boolean isTokenPropagation() { - return ConfigProvider.getConfig() - .getOptionalValue(getCanonicalAuthConfigPropertyName(AuthConfig.TOKEN_PROPAGATION), Boolean.class) - .orElse(false); + return isTokenPropagation(getOpenApiSpecId(), getName()); } - public String getTokenForPropagation(MultivaluedMap httpHeaders) { - String propagatedHeaderName = propagationHeaderName(getOpenApiSpecId(), getName(), getHeaderForPropagation()); - return Objects.toString(httpHeaders.getFirst(propagatedHeaderName), null); + public static String getTokenForPropagation(MultivaluedMap httpHeaders, String openApiSpecId, + String authName) { + String headerName = getHeaderName(openApiSpecId, authName) != null ? getHeaderName(openApiSpecId, authName) + : HttpHeaders.AUTHORIZATION; + String propagatedHeaderName = propagationHeaderName(openApiSpecId, authName, headerName); + return Objects.toString(httpHeaders.getFirst(propagatedHeaderName)); } - public String getHeaderForPropagation() { - return getHeaderName() != null ? getHeaderName() : HttpHeaders.AUTHORIZATION; + public String getTokenForPropagation(MultivaluedMap httpHeaders) { + return getTokenForPropagation(httpHeaders, getOpenApiSpecId(), getName()); } public String getHeaderName() { @@ -80,6 +80,13 @@ public String getHeaderName() { .getOptionalValue(getCanonicalAuthConfigPropertyName(AuthConfig.HEADER_NAME), String.class).orElse(null); } + public static String getHeaderName(String openApiSpecId, String authName) { + return ConfigProvider.getConfig() + .getOptionalValue(getCanonicalAuthConfigPropertyName(AuthConfig.HEADER_NAME, openApiSpecId, authName), + String.class) + .orElse(null); + } + @Override public List operationsToFilter() { return applyToOperations; @@ -93,11 +100,14 @@ public static String getCanonicalAuthConfigPropertyName(String authPropertyName, return String.format(CANONICAL_AUTH_CONFIG_PROPERTY_NAME, openApiSpecId, authName, authPropertyName); } - protected void addAuthorizationHeader(MultivaluedMap headers, String value) { - headers.put(HttpHeaders.AUTHORIZATION, Collections.singletonList(value)); + public static boolean isTokenPropagation(String openApiSpecId, String authName) { + return ConfigProvider.getConfig() + .getOptionalValue(getCanonicalAuthConfigPropertyName(AuthConfig.TOKEN_PROPAGATION, openApiSpecId, authName), + Boolean.class) + .orElse(false); } - protected static boolean isEmptyOrBlank(String value) { - return value == null || value.isBlank(); + public CredentialsProvider getCredentialsProvider() { + return credentialsProvider; } -} +} \ No newline at end of file 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 2f3db8393..f2467eb14 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 @@ -59,7 +59,11 @@ && isUseAuthorizationHeaderValue()) { } private String getApiKey(ClientRequestContext requestContext) { - return credentialsProvider.getApiKey(requestContext, getOpenApiSpecId(), getName()); + return credentialsProvider.getApiKey(CredentialsProvider.CredentialsContext.builder() + .requestContext(requestContext) + .openApiSpecId(getOpenApiSpecId()) + .authName(getName()) + .build()); } private boolean isUseAuthorizationHeaderValue() { 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 343b2e18d..854ac1123 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 @@ -29,11 +29,19 @@ public BasicAuthenticationProvider(final String openApiSpecId, String name, List } private String getUsername(ClientRequestContext requestContext) { - return credentialsProvider.getBasicUsername(requestContext, getOpenApiSpecId(), getName()); + return credentialsProvider.getBasicUsername(CredentialsProvider.CredentialsContext.builder() + .requestContext(requestContext) + .openApiSpecId(getOpenApiSpecId()) + .authName(getName()) + .build()); } private String getPassword(ClientRequestContext requestContext) { - return credentialsProvider.getBasicPassword(requestContext, getOpenApiSpecId(), getName()); + return credentialsProvider.getBasicPassword(CredentialsProvider.CredentialsContext.builder() + .requestContext(requestContext) + .openApiSpecId(getOpenApiSpecId()) + .authName(getName()) + .build()); } @Override 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 d5dae2a74..8cc70db0c 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 @@ -51,6 +51,10 @@ public void filter(ClientRequestContext requestContext) throws IOException { } private String getBearerToken(ClientRequestContext requestContext) { - return credentialsProvider.getBearerToken(requestContext, getOpenApiSpecId(), getName()); + return credentialsProvider.getBearerToken(CredentialsProvider.CredentialsContext.builder() + .requestContext(requestContext) + .openApiSpecId(getOpenApiSpecId()) + .authName(getName()) + .build()); } } diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java index 8f78ee1e8..00ee1e142 100644 --- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java +++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java @@ -3,7 +3,7 @@ import jakarta.annotation.Priority; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Alternative; -import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.core.HttpHeaders; import org.eclipse.microprofile.config.ConfigProvider; import org.slf4j.Logger; @@ -26,41 +26,53 @@ public ConfigCredentialsProvider() { } @Override - public String getApiKey(ClientRequestContext requestContext, String openApiSpecId, String authName) { + public String getApiKey(CredentialsContext input) { final String key = ConfigProvider.getConfig() - .getOptionalValue(AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, openApiSpecId, authName), + .getOptionalValue( + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, input.getOpenApiSpecId(), + input.getAuthName()), String.class) .orElse(""); if (key.isEmpty()) { LOGGER.warn("configured {} property (see application.properties) is empty. hint: configure it.", - AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, openApiSpecId, authName)); + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, input.getOpenApiSpecId(), + input.getAuthName())); } return key; } @Override - public String getBasicUsername(ClientRequestContext requestContext, String openApiSpecId, String authName) { + public String getBasicUsername(CredentialsContext input) { return ConfigProvider.getConfig() - .getOptionalValue(AbstractAuthProvider.getCanonicalAuthConfigPropertyName(USER_NAME, openApiSpecId, authName), + .getOptionalValue( + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(USER_NAME, input.getOpenApiSpecId(), + input.getAuthName()), String.class) .orElse(""); } @Override - public String getBasicPassword(ClientRequestContext requestContext, String openApiSpecId, String authName) { + public String getBasicPassword(CredentialsContext input) { return ConfigProvider.getConfig() - .getOptionalValue(AbstractAuthProvider.getCanonicalAuthConfigPropertyName(PASSWORD, openApiSpecId, authName), + .getOptionalValue( + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(PASSWORD, input.getOpenApiSpecId(), + input.getAuthName()), String.class) .orElse(""); } @Override - public String getBearerToken(ClientRequestContext requestContext, String openApiSpecId, String authName) { + public String getBearerToken(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( - AbstractAuthProvider.getCanonicalAuthConfigPropertyName(BEARER_TOKEN, openApiSpecId, authName), + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(BEARER_TOKEN, input.getOpenApiSpecId(), + input.getAuthName()), String.class) .orElse(""); } + @Override + public String getOauth2BearerToken(CredentialsContext input) { + return input.getRequestContext().getHeaderString(HttpHeaders.AUTHORIZATION); + } } diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java index 3f15dd67c..02c4fa787 100644 --- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java +++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java @@ -12,36 +12,96 @@ public interface CredentialsProvider { /** * Gets the API Key given the OpenAPI definition and security schema * - * @param openApiSpecId the OpenAPI Spec identification as defined by the OpenAPI Extension - * @param authName The security schema for this API Key definition + * @param input the input data available to the method * @return the API Key to use when filtering the request */ - String getApiKey(ClientRequestContext requestContext, String openApiSpecId, String authName); + String getApiKey(CredentialsContext input); /** * Gets the username given the OpenAPI definition and security schema * - * @param openApiSpecId the OpenAPI Spec identification as defined by the OpenAPI Extension - * @param authName The security schema for this Basic Authorization definition + * @param input the input data available to the method * @return the username to use when filtering the request */ - String getBasicUsername(ClientRequestContext requestContext, String openApiSpecId, String authName); + String getBasicUsername(CredentialsContext input); /** * Gets the password given the OpenAPI definition and security schema * - * @param openApiSpecId the OpenAPI Spec identification as defined by the OpenAPI Extension - * @param authName The security schema for this Basic Authorization definition + * @param input the input data available to the method * @return the password to use when filtering the request */ - String getBasicPassword(ClientRequestContext requestContext, String openApiSpecId, String authName); + String getBasicPassword(CredentialsContext input); /** * Gets the Bearer Token given the OpenAPI definition and security schema * - * @param openApiSpecId the OpenAPI Spec identification as defined by the OpenAPI Extension - * @param authName The security schema for this Bearer Token definition + * @param input the input data available to the method * @return the Bearer Token to use when filtering the request */ - String getBearerToken(ClientRequestContext requestContext, String openApiSpecId, String authName); + String getBearerToken(CredentialsContext input); + + /** + * Gets the OAuth2 Bearer Token given the OpenAPI definition and security schema + * + * @param input the input data available to the method + * @return the Bearer Token to use when filtering the request + */ + String getOauth2BearerToken(CredentialsContext input); + + class CredentialsContext { + // requestContext The current request context in which set the authorization header token + private ClientRequestContext requestContext; + // openApiSpecId the OpenAPI Spec identification as defined by the OpenAPI Extension + private String openApiSpecId; + // authName The security schema for this Bearer Token definition + private String authName; + + public CredentialsContext(ClientRequestContext requestContext, String openApiSpecId, String authName) { + this.requestContext = requestContext; + this.openApiSpecId = openApiSpecId; + this.authName = authName; + } + + public ClientRequestContext getRequestContext() { + return requestContext; + } + + public String getOpenApiSpecId() { + return openApiSpecId; + } + + public String getAuthName() { + return authName; + } + + public static CredentialsContextBuilder builder() { + return new CredentialsContextBuilder(); + } + + public static class CredentialsContextBuilder { + private ClientRequestContext requestContext; + private String openApiSpecId; + private String authName; + + public CredentialsContextBuilder requestContext(ClientRequestContext requestContext) { + this.requestContext = requestContext; + return this; + } + + public CredentialsContextBuilder openApiSpecId(String openApiSpecId) { + this.openApiSpecId = openApiSpecId; + return this; + } + + public CredentialsContextBuilder authName(String authName) { + this.authName = authName; + return this; + } + + public CredentialsContext build() { + return new CredentialsContext(requestContext, openApiSpecId, authName); + } + } + } } diff --git a/docs/modules/ROOT/pages/includes/custom-auth-provider.adoc b/docs/modules/ROOT/pages/includes/custom-auth-provider.adoc index 6d2c5b5a2..b5984c931 100644 --- a/docs/modules/ROOT/pages/includes/custom-auth-provider.adoc +++ b/docs/modules/ROOT/pages/includes/custom-auth-provider.adoc @@ -27,7 +27,7 @@ import io.quarkiverse.openapi.generator.providers.CredentialsProvider; @RequestScoped @Alternative -@Priority(10) // A higher priority than the default provider. +@Priority(200) // A higher priority than the default provider. public class RuntimeCredentialsProvider implements CredentialsProvider { @Override From 09f772a3f75ca5b82f001103ac1d6de2ab4c8a01 Mon Sep 17 00:00:00 2001 From: gabriel-farache Date: Fri, 6 Jun 2025 19:51:16 +0200 Subject: [PATCH 2/8] Fix #1175: remove wrong auth provider constructors (#1176) Signed-off-by: gabriel-farache --- .../auth/DummyApiKeyAuthenticationProvider.java | 3 ++- .../oidc/providers/OAuth2AuthenticationProvider.java | 6 ------ .../oidc/OAuth2AuthenticationProviderTest.java | 4 +++- .../ReactiveOAuth2AuthenticationProviderTest.java | 4 +++- .../providers/ApiKeyAuthenticationProvider.java | 5 ----- .../providers/BasicAuthenticationProvider.java | 4 ---- .../providers/BearerAuthenticationProvider.java | 5 ----- .../providers/ApiKeyOpenApiSpecProviderTest.java | 11 ++++++----- .../providers/BasicOpenApiSpecProviderTest.java | 3 ++- .../providers/BearerOpenApiSpecProviderTest.java | 4 ++-- 10 files changed, 18 insertions(+), 31 deletions(-) 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 1096cca18..2d60e0e44 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 @@ -12,6 +12,7 @@ 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.ConfigCredentialsProvider; @Priority(Priorities.AUTHENTICATION) public class DummyApiKeyAuthenticationProvider implements ClientRequestFilter { @@ -21,7 +22,7 @@ public class DummyApiKeyAuthenticationProvider implements ClientRequestFilter { @PostConstruct public void init() { authProvider = new ApiKeyAuthenticationProvider("open_weather_custom_security_yaml", "app_id", ApiKeyIn.query, "appid", - List.of()); + List.of(), new ConfigCredentialsProvider()); } @Override diff --git a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java index 541d47220..ec9bd765f 100644 --- a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java +++ b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java @@ -13,7 +13,6 @@ import io.quarkiverse.openapi.generator.providers.AbstractAuthProvider; import io.quarkiverse.openapi.generator.providers.AuthUtils; -import io.quarkiverse.openapi.generator.providers.ConfigCredentialsProvider; import io.quarkiverse.openapi.generator.providers.CredentialsProvider; import io.quarkiverse.openapi.generator.providers.OperationAuthInfo; @@ -31,11 +30,6 @@ public OAuth2AuthenticationProvider(String name, validateConfig(); } - public OAuth2AuthenticationProvider(String name, - String openApiSpecId, OidcClientRequestFilterDelegate delegate, List operations) { - this(name, openApiSpecId, delegate, operations, new ConfigCredentialsProvider()); - } - @Override public void filter(ClientRequestContext requestContext) throws IOException { String bearerToken; diff --git a/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java index 8eaa1e2dc..aa54b54b7 100644 --- a/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java +++ b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/OAuth2AuthenticationProviderTest.java @@ -29,6 +29,7 @@ import io.quarkiverse.openapi.generator.AuthConfig; import io.quarkiverse.openapi.generator.oidc.providers.OAuth2AuthenticationProvider; +import io.quarkiverse.openapi.generator.providers.ConfigCredentialsProvider; import io.quarkus.oidc.client.Tokens; @ExtendWith(MockitoExtension.class) @@ -70,7 +71,8 @@ void setUp() { } private OAuth2AuthenticationProvider createClassicProvider() { - return new OAuth2AuthenticationProvider(AUTH_SCHEME_NAME, OPEN_API_FILE_SPEC_ID, classicDelegate, List.of()); + return new OAuth2AuthenticationProvider(AUTH_SCHEME_NAME, OPEN_API_FILE_SPEC_ID, classicDelegate, List.of(), + new ConfigCredentialsProvider()); } private void assertHeader(MultivaluedMap headers, String headerName, String value) { diff --git a/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java index 68169a3d8..a450f3cb2 100644 --- a/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java +++ b/client/oidc/src/test/java/io/quarkiverse/openapi/generator/oidc/ReactiveOAuth2AuthenticationProviderTest.java @@ -31,6 +31,7 @@ import io.quarkiverse.openapi.generator.AuthConfig; import io.quarkiverse.openapi.generator.oidc.providers.OAuth2AuthenticationProvider; +import io.quarkiverse.openapi.generator.providers.ConfigCredentialsProvider; import io.quarkus.oidc.client.Tokens; import io.smallrye.mutiny.Uni; @@ -79,7 +80,8 @@ void setUp() { } protected OAuth2AuthenticationProvider createReactiveProvider() { - return new OAuth2AuthenticationProvider(AUTH_SCHEME_NAME, OPEN_API_FILE_SPEC_ID, reactiveDelegate, List.of()); + return new OAuth2AuthenticationProvider(AUTH_SCHEME_NAME, OPEN_API_FILE_SPEC_ID, reactiveDelegate, List.of(), + new ConfigCredentialsProvider()); } protected void assertHeader(MultivaluedMap headers, String headerName, String value) { 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 f2467eb14..2b2368e44 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 @@ -31,11 +31,6 @@ public ApiKeyAuthenticationProvider(final String openApiSpecId, final String nam validateConfig(); } - public ApiKeyAuthenticationProvider(final String openApiSpecId, final String name, final ApiKeyIn apiKeyIn, - final String apiKeyName, List operations) { - this(openApiSpecId, name, apiKeyIn, apiKeyName, operations, new ConfigCredentialsProvider()); - } - @Override public void filter(ClientRequestContext requestContext) throws IOException { switch (apiKeyIn) { 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 854ac1123..64a9cba7c 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 @@ -24,10 +24,6 @@ public BasicAuthenticationProvider(final String openApiSpecId, String name, List super(name, openApiSpecId, operations, credentialsProvider); } - public BasicAuthenticationProvider(final String openApiSpecId, String name, List operations) { - this(openApiSpecId, name, operations, new ConfigCredentialsProvider()); - } - private String getUsername(ClientRequestContext requestContext) { return credentialsProvider.getBasicUsername(CredentialsProvider.CredentialsContext.builder() .requestContext(requestContext) 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 8cc70db0c..2bbc80a39 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 @@ -27,11 +27,6 @@ public BearerAuthenticationProvider(final String openApiSpecId, final String nam this.scheme = scheme; } - public BearerAuthenticationProvider(final String openApiSpecId, final String name, final String scheme, - List operations) { - this(openApiSpecId, name, scheme, operations, new ConfigCredentialsProvider()); - } - @Override public void filter(ClientRequestContext requestContext) throws IOException { String bearerToken = getBearerToken(requestContext); diff --git a/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyOpenApiSpecProviderTest.java b/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyOpenApiSpecProviderTest.java index d6ffd6fab..d8060fb4f 100644 --- a/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyOpenApiSpecProviderTest.java +++ b/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyOpenApiSpecProviderTest.java @@ -42,7 +42,7 @@ class ApiKeyOpenApiSpecProviderTest extends AbstractOpenApiSpecProviderTest headers = new MultivaluedTreeMap<>(); doReturn(headers).when(requestContext).getHeaders(); provider = new ApiKeyAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, ApiKeyIn.cookie, API_KEY_NAME, - List.of()); + List.of(), new ConfigCredentialsProvider()); provider.filter(requestContext); final List cookies = headers.get(HttpHeaders.COOKIE); assertThat(cookies).singleElement().satisfies(cookie -> assertCookie(cookie, API_KEY_NAME, API_KEY_VALUE)); @@ -114,7 +114,7 @@ void filterCookieCaseExisting() throws IOException { headers.add(HttpHeaders.COOKIE, existingCookie); doReturn(headers).when(requestContext).getHeaders(); provider = new ApiKeyAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, ApiKeyIn.cookie, API_KEY_NAME, - List.of()); + List.of(), new ConfigCredentialsProvider()); provider.filter(requestContext); final List cookies = headers.get(HttpHeaders.COOKIE); assertThat(cookies).satisfiesExactlyInAnyOrder(cookie -> assertCookie(cookie, existingCookieName, existingCookieValue), @@ -130,7 +130,8 @@ void tokenPropagationNotSupported() { Boolean.class)).thenReturn(Optional.of(true)); assertThatThrownBy(() -> new ApiKeyAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, ApiKeyIn.header, - API_KEY_NAME, List.of())).hasMessageContaining("quarkus.openapi-generator.%s.auth.%s.token-propagation", + API_KEY_NAME, List.of(), new ConfigCredentialsProvider())) + .hasMessageContaining("quarkus.openapi-generator.%s.auth.%s.token-propagation", OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME); } } diff --git a/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/BasicOpenApiSpecProviderTest.java b/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/BasicOpenApiSpecProviderTest.java index 20a26d577..2677a7786 100644 --- a/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/BasicOpenApiSpecProviderTest.java +++ b/client/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/BasicOpenApiSpecProviderTest.java @@ -39,7 +39,8 @@ class BasicOpenApiSpecProviderTest extends AbstractOpenApiSpecProviderTest filterWithPropagationTestValues() { @Override protected BearerAuthenticationProvider createProvider() { return new BearerAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, null, - List.of()); + List.of(), new ConfigCredentialsProvider()); } @Test @@ -64,7 +64,7 @@ void filterCustomSchemaCase() throws IOException { private void filter(String bearerScheme, String expectedAuthorizationHeader) throws IOException { provider = new BearerAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, bearerScheme, - List.of()); + List.of(), new ConfigCredentialsProvider()); provider.filter(requestContext); assertHeader(headers, HttpHeaders.AUTHORIZATION, expectedAuthorizationHeader); } From 6e7a1c5b5b9f82775f2cdbc0bfde695252920329 Mon Sep 17 00:00:00 2001 From: gabriel-farache Date: Tue, 10 Jun 2025 17:54:25 +0200 Subject: [PATCH 3/8] Apply late feedback of PR #1126 (#1173) Signed-off-by: gabriel-farache --- .../provider/CustomCredentialsProvider.java | 1 + .../it/creds/CustomCredentialsProvider.java | 1 + .../OAuth2AuthenticationProvider.java | 3 +- .../ApiKeyAuthenticationProvider.java | 2 +- .../BasicAuthenticationProvider.java | 4 +- .../BearerAuthenticationProvider.java | 2 +- .../providers/CredentialsContext.java | 59 +++++++++++++++++++ .../providers/CredentialsProvider.java | 58 ------------------ 8 files changed, 67 insertions(+), 63 deletions(-) create mode 100644 client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsContext.java diff --git a/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java index e2bc1b8af..070c7fd5a 100644 --- a/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java +++ b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java @@ -6,6 +6,7 @@ import jakarta.enterprise.inject.Specializes; import io.quarkiverse.openapi.generator.providers.ConfigCredentialsProvider; +import io.quarkiverse.openapi.generator.providers.CredentialsContext; @Dependent @Alternative diff --git a/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java b/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java index 8bbc39b68..48d368604 100644 --- a/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java +++ b/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; import io.quarkiverse.openapi.generator.providers.ConfigCredentialsProvider; +import io.quarkiverse.openapi.generator.providers.CredentialsContext; @Dependent @Alternative diff --git a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java index ec9bd765f..8c1f3f236 100644 --- a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java +++ b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java @@ -13,6 +13,7 @@ import io.quarkiverse.openapi.generator.providers.AbstractAuthProvider; import io.quarkiverse.openapi.generator.providers.AuthUtils; +import io.quarkiverse.openapi.generator.providers.CredentialsContext; import io.quarkiverse.openapi.generator.providers.CredentialsProvider; import io.quarkiverse.openapi.generator.providers.OperationAuthInfo; @@ -38,7 +39,7 @@ public void filter(ClientRequestContext requestContext) throws IOException { bearerToken = this.getTokenForPropagation(requestContext.getHeaders()); } else { delegate.filter(requestContext); - bearerToken = this.getCredentialsProvider().getOauth2BearerToken(CredentialsProvider.CredentialsContext.builder() + bearerToken = this.getCredentialsProvider().getOauth2BearerToken(CredentialsContext.builder() .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) 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 2b2368e44..3cf740ba2 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 @@ -54,7 +54,7 @@ && isUseAuthorizationHeaderValue()) { } private String getApiKey(ClientRequestContext requestContext) { - return credentialsProvider.getApiKey(CredentialsProvider.CredentialsContext.builder() + return credentialsProvider.getApiKey(CredentialsContext.builder() .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) 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 64a9cba7c..183ad1142 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 @@ -25,7 +25,7 @@ public BasicAuthenticationProvider(final String openApiSpecId, String name, List } private String getUsername(ClientRequestContext requestContext) { - return credentialsProvider.getBasicUsername(CredentialsProvider.CredentialsContext.builder() + return credentialsProvider.getBasicUsername(CredentialsContext.builder() .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) @@ -33,7 +33,7 @@ private String getUsername(ClientRequestContext requestContext) { } private String getPassword(ClientRequestContext requestContext) { - return credentialsProvider.getBasicPassword(CredentialsProvider.CredentialsContext.builder() + return credentialsProvider.getBasicPassword(CredentialsContext.builder() .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) 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 2bbc80a39..cd1eb5cf9 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 @@ -46,7 +46,7 @@ public void filter(ClientRequestContext requestContext) throws IOException { } private String getBearerToken(ClientRequestContext requestContext) { - return credentialsProvider.getBearerToken(CredentialsProvider.CredentialsContext.builder() + return credentialsProvider.getBearerToken(CredentialsContext.builder() .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsContext.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsContext.java new file mode 100644 index 000000000..3c47b0923 --- /dev/null +++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsContext.java @@ -0,0 +1,59 @@ +package io.quarkiverse.openapi.generator.providers; + +import jakarta.ws.rs.client.ClientRequestContext; + +public class CredentialsContext { + // requestContext The current request context in which set the authorization header token + private ClientRequestContext requestContext; + // openApiSpecId the OpenAPI Spec identification as defined by the OpenAPI Extension + private String openApiSpecId; + // authName The security schema for this Bearer Token definition + private String authName; + + public CredentialsContext(ClientRequestContext requestContext, String openApiSpecId, String authName) { + this.requestContext = requestContext; + this.openApiSpecId = openApiSpecId; + this.authName = authName; + } + + public ClientRequestContext getRequestContext() { + return requestContext; + } + + public String getOpenApiSpecId() { + return openApiSpecId; + } + + public String getAuthName() { + return authName; + } + + public static CredentialsContextBuilder builder() { + return new CredentialsContextBuilder(); + } + + public static class CredentialsContextBuilder { + private ClientRequestContext requestContext; + private String openApiSpecId; + private String authName; + + public CredentialsContextBuilder requestContext(ClientRequestContext requestContext) { + this.requestContext = requestContext; + return this; + } + + public CredentialsContextBuilder openApiSpecId(String openApiSpecId) { + this.openApiSpecId = openApiSpecId; + return this; + } + + public CredentialsContextBuilder authName(String authName) { + this.authName = authName; + return this; + } + + public CredentialsContext build() { + return new CredentialsContext(requestContext, openApiSpecId, authName); + } + } +} diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java index 02c4fa787..83d15a74d 100644 --- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java +++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java @@ -1,7 +1,5 @@ package io.quarkiverse.openapi.generator.providers; -import jakarta.ws.rs.client.ClientRequestContext; - /** * Provider for security credentials. Clients can implement this interface to control how to provide security credentials in * runtime. @@ -48,60 +46,4 @@ public interface CredentialsProvider { * @return the Bearer Token to use when filtering the request */ String getOauth2BearerToken(CredentialsContext input); - - class CredentialsContext { - // requestContext The current request context in which set the authorization header token - private ClientRequestContext requestContext; - // openApiSpecId the OpenAPI Spec identification as defined by the OpenAPI Extension - private String openApiSpecId; - // authName The security schema for this Bearer Token definition - private String authName; - - public CredentialsContext(ClientRequestContext requestContext, String openApiSpecId, String authName) { - this.requestContext = requestContext; - this.openApiSpecId = openApiSpecId; - this.authName = authName; - } - - public ClientRequestContext getRequestContext() { - return requestContext; - } - - public String getOpenApiSpecId() { - return openApiSpecId; - } - - public String getAuthName() { - return authName; - } - - public static CredentialsContextBuilder builder() { - return new CredentialsContextBuilder(); - } - - public static class CredentialsContextBuilder { - private ClientRequestContext requestContext; - private String openApiSpecId; - private String authName; - - public CredentialsContextBuilder requestContext(ClientRequestContext requestContext) { - this.requestContext = requestContext; - return this; - } - - public CredentialsContextBuilder openApiSpecId(String openApiSpecId) { - this.openApiSpecId = openApiSpecId; - return this; - } - - public CredentialsContextBuilder authName(String authName) { - this.authName = authName; - return this; - } - - public CredentialsContext build() { - return new CredentialsContext(requestContext, openApiSpecId, authName); - } - } - } } From 3ebe6f2ddc248ad2258a54622b087739ce17c622 Mon Sep 17 00:00:00 2001 From: gabriel-farache Date: Tue, 10 Jun 2025 21:20:26 +0200 Subject: [PATCH 4/8] Fix #1180: also look into outgoing header while propagating Signed-off-by: gabriel-farache --- ...tAuthenticationPropagationHeadersFactory.java | 16 +++++++++++++++- .../providers/BearerAuthenticationProvider.java | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletion(-) 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 2f9c1a04e..069c7cffb 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 @@ -7,6 +7,8 @@ import jakarta.ws.rs.core.MultivaluedMap; import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.quarkiverse.openapi.generator.OpenApiGeneratorConfig; @@ -23,6 +25,8 @@ public abstract class AbstractAuthenticationPropagationHeadersFactory implements protected OpenApiGeneratorConfig generatorConfig; protected HeadersProvider headersProvider; + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAuthenticationPropagationHeadersFactory.class); + protected AbstractAuthenticationPropagationHeadersFactory(BaseCompositeAuthenticationProvider compositeProvider, OpenApiGeneratorConfig generatorConfig, HeadersProvider headersProvider) { @@ -36,6 +40,11 @@ public MultivaluedMap update(MultivaluedMap inco MultivaluedMap clientOutgoingHeaders) { MultivaluedMap propagatedHeaders = new MultivaluedHashMap<>(); MultivaluedMap providedHeaders = headersProvider.getStringHeaders(generatorConfig); + + LOGGER.debug("Incoming headers keys{}", incomingHeaders.keySet()); + LOGGER.debug("Outgoing headers keys{}", clientOutgoingHeaders.keySet()); + LOGGER.debug("Provided headers keys{}", providedHeaders.keySet()); + compositeProvider.getAuthenticationProviders().stream() .filter(AbstractAuthProvider.class::isInstance) .map(AbstractAuthProvider.class::cast) @@ -46,9 +55,14 @@ public MultivaluedMap update(MultivaluedMap inco // get priority to the headers coming from the headers provider. List headerValue = providedHeaders.get(headerName); if (headerValue == null) { - // lastly look into the incoming headers. + // next, look into the incoming headers. headerValue = incomingHeaders.get(headerName); } + if (headerValue == null) { + // lastly look into the outgoing headers. + headerValue = clientOutgoingHeaders.get(headerName); + } + if (headerValue != null) { propagatedHeaders.put(propagationHeaderName(authProvider.getOpenApiSpecId(), authProvider.getName(), 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 cd1eb5cf9..4c29d095a 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 @@ -10,6 +10,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Provides bearer token authentication or any other valid scheme. * @@ -20,6 +23,7 @@ public class BearerAuthenticationProvider extends AbstractAuthProvider { private static final Logger LOGGER = LoggerFactory.getLogger(BearerAuthenticationProvider.class); private final String scheme; + private static final Logger LOGGER = LoggerFactory.getLogger(BearerAuthenticationProvider.class); public BearerAuthenticationProvider(final String openApiSpecId, final String name, final String scheme, List operations, CredentialsProvider credentialsProvider) { @@ -29,6 +33,7 @@ public BearerAuthenticationProvider(final String openApiSpecId, final String nam @Override public void filter(ClientRequestContext requestContext) throws IOException { + LOGGER.debug("Headers keys set in incoming requestContext: {}", requestContext.getHeaders().keySet()); String bearerToken = getBearerToken(requestContext); if (isTokenPropagation()) { @@ -43,6 +48,7 @@ public void filter(ClientRequestContext requestContext) throws IOException { getName(), getCanonicalAuthConfigPropertyName(BEARER_TOKEN, getOpenApiSpecId(), getName()), getHeaderForPropagation()); } + LOGGER.debug("Header keys set in filtered requestContext: {}", requestContext.getHeaders().keySet()); } private String getBearerToken(ClientRequestContext requestContext) { From c55c7c39d9fd32e764bd3cfacca3a4627099c8db Mon Sep 17 00:00:00 2001 From: Walter Medvedeo Date: Thu, 12 Jun 2025 15:36:50 +0200 Subject: [PATCH 5/8] issue-1182: Token propagation throws java.lang.UnsupportedOperationException when adding the token to the request header parameters (#1184) (#1189) * issue-1182: Token propagation throws java.lang.UnsupportedOperationException when adding the token to the request header parameters * Review comments 1 * Review comments 2 (cherry picked from commit c6e504a2ae690ed6b7287dd77c591516127a3694) --- .../OAuth2AuthenticationProvider.java | 11 +++++---- .../providers/AbstractAuthProvider.java | 23 +++++++++++++++---- .../BasicAuthenticationProvider.java | 2 +- .../BearerAuthenticationProvider.java | 7 +----- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java index 8c1f3f236..8f2e916dd 100644 --- a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java +++ b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java @@ -6,7 +6,6 @@ import java.util.List; import jakarta.ws.rs.client.ClientRequestContext; -import jakarta.ws.rs.core.HttpHeaders; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,10 +45,14 @@ public void filter(ClientRequestContext requestContext) throws IOException { .build()); } - if (bearerToken != null && !bearerToken.isBlank()) { - requestContext.getHeaders().remove(HttpHeaders.AUTHORIZATION); - requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, + if (!isEmptyOrBlank(bearerToken)) { + addAuthorizationHeader(requestContext.getHeaders(), AuthUtils.authTokenOrBearer("Bearer", AbstractAuthProvider.sanitizeBearerToken(bearerToken))); + } else { + LOGGER.debug("No bearer token was found for the oauth2 security scheme: {}." + + " You must verify that a Quarkus OIDC Client with the name: {} is properly configured," + + " or the request header: {} is set when the token propagation is enabled.", + getName(), getName(), getHeaderForPropagation(getOpenApiSpecId(), getName())); } } 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 93e910abd..a08a191ac 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 @@ -4,9 +4,11 @@ import static io.quarkiverse.openapi.generator.providers.AbstractAuthenticationPropagationHeadersFactory.propagationHeaderName; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; +import io.vertx.codegen.doc.Token; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MultivaluedMap; @@ -64,17 +66,21 @@ public boolean isTokenPropagation() { } public static String getTokenForPropagation(MultivaluedMap httpHeaders, String openApiSpecId, - String authName) { - String headerName = getHeaderName(openApiSpecId, authName) != null ? getHeaderName(openApiSpecId, authName) - : HttpHeaders.AUTHORIZATION; + String authName) { + String headerName = getHeaderForPropagation(openApiSpecId, authName); String propagatedHeaderName = propagationHeaderName(openApiSpecId, authName, headerName); - return Objects.toString(httpHeaders.getFirst(propagatedHeaderName)); + return Objects.toString(httpHeaders.getFirst(propagatedHeaderName), null); } public String getTokenForPropagation(MultivaluedMap httpHeaders) { return getTokenForPropagation(httpHeaders, getOpenApiSpecId(), getName()); } + public static String getHeaderForPropagation(String openApiSpecId, String authName) { + return getHeaderName(openApiSpecId, authName) != null ? getHeaderName(openApiSpecId, authName) + : HttpHeaders.AUTHORIZATION; + } + public String getHeaderName() { return ConfigProvider.getConfig() .getOptionalValue(getCanonicalAuthConfigPropertyName(AuthConfig.HEADER_NAME), String.class).orElse(null); @@ -110,4 +116,13 @@ public static boolean isTokenPropagation(String openApiSpecId, String authName) public CredentialsProvider getCredentialsProvider() { return credentialsProvider; } + + + protected void addAuthorizationHeader(MultivaluedMap headers, String value) { + headers.put(HttpHeaders.AUTHORIZATION, Collections.singletonList(value)); + } + + protected static boolean isEmptyOrBlank(String value) { + return value == null || value.isBlank(); + } } \ No newline at end of file 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 183ad1142..6b25671c5 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 @@ -57,7 +57,7 @@ public void filter(ClientRequestContext requestContext) throws IOException { " You must verify that the properties: {} and {} are properly configured, or the request header: {} is set when the token propagation is enabled.", getName(), getCanonicalAuthConfigPropertyName(USER_NAME, getOpenApiSpecId(), getName()), getCanonicalAuthConfigPropertyName(PASSWORD, getOpenApiSpecId(), getName()), - getHeaderForPropagation()); + getHeaderForPropagation(getOpenApiSpecId(), getName())); } } } 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 4c29d095a..12a1e9af4 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 @@ -10,9 +10,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Provides bearer token authentication or any other valid scheme. * @@ -20,8 +17,6 @@ */ public class BearerAuthenticationProvider extends AbstractAuthProvider { - private static final Logger LOGGER = LoggerFactory.getLogger(BearerAuthenticationProvider.class); - private final String scheme; private static final Logger LOGGER = LoggerFactory.getLogger(BearerAuthenticationProvider.class); @@ -46,7 +41,7 @@ public void filter(ClientRequestContext requestContext) throws IOException { LOGGER.debug("No bearer token was found for the security scheme: {}." + " You must verify that the property: {} is properly configured, or the request header: {} is set when the token propagation is enabled.", getName(), getCanonicalAuthConfigPropertyName(BEARER_TOKEN, getOpenApiSpecId(), getName()), - getHeaderForPropagation()); + getHeaderForPropagation(getOpenApiSpecId(), getName())); } LOGGER.debug("Header keys set in filtered requestContext: {}", requestContext.getHeaders().keySet()); } From 10aa5abc10fa1faee1b106150e0f4e1a82da08d8 Mon Sep 17 00:00:00 2001 From: gabriel-farache Date: Wed, 18 Jun 2025 15:47:49 +0200 Subject: [PATCH 6/8] Fix #1191 - refactor CredentialsProvider return type (#1192) * Fix #1191 - refactor CredentialsProvider return type * Apply feedback Signed-off-by: gabriel-farache * Better log message for oauth2 provider Signed-off-by: gabriel-farache --------- Signed-off-by: gabriel-farache --- .../provider/CustomCredentialsProvider.java | 12 +++--- .../it/creds/CustomCredentialsProvider.java | 8 ++-- .../OAuth2AuthenticationProvider.java | 37 +++++++++++++------ .../ApiKeyAuthenticationProvider.java | 17 ++++++++- .../BasicAuthenticationProvider.java | 4 +- .../BearerAuthenticationProvider.java | 2 +- .../providers/ConfigCredentialsProvider.java | 36 +++++++----------- .../providers/CredentialsProvider.java | 12 +++--- 8 files changed, 76 insertions(+), 52 deletions(-) diff --git a/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java index 070c7fd5a..b9022e801 100644 --- a/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java +++ b/client/integration-tests/auth-provider/src/main/java/io/quarkiverse/openapi/generator/it/auth/provider/CustomCredentialsProvider.java @@ -1,5 +1,7 @@ package io.quarkiverse.openapi.generator.it.auth.provider; +import java.util.Optional; + import jakarta.annotation.Priority; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Alternative; @@ -11,18 +13,18 @@ @Dependent @Alternative @Specializes -@Priority(200) +@Priority(201) public class CustomCredentialsProvider extends ConfigCredentialsProvider { public CustomCredentialsProvider() { } @Override - public String getBearerToken(CredentialsContext input) { - return super.getBearerToken(input) + "_TEST"; + public Optional getBearerToken(CredentialsContext input) { + return Optional.of("BEARER_TOKEN_TEST"); } @Override - public String getOauth2BearerToken(CredentialsContext input) { - return super.getOauth2BearerToken(input) + "_TEST"; + public Optional getOauth2BearerToken(CredentialsContext input) { + return Optional.of("KEYCLOAK_ACCESS_TOKEN_TEST"); } } diff --git a/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java b/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java index 48d368604..00a445982 100644 --- a/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java +++ b/client/integration-tests/override-credential-provider/src/main/java/io/quarkiverse/openapi/generator/it/creds/CustomCredentialsProvider.java @@ -1,5 +1,7 @@ package io.quarkiverse.openapi.generator.it.creds; +import java.util.Optional; + import jakarta.annotation.Priority; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Alternative; @@ -19,8 +21,8 @@ public class CustomCredentialsProvider extends ConfigCredentialsProvider { public static String TOKEN = "FIXED_TEST_TOKEN"; @Override - public String getBearerToken(CredentialsContext input) { + public Optional getBearerToken(CredentialsContext input) { LOGGER.info("========> getBearerToken from CustomCredentialsProvider"); - return TOKEN; + return Optional.of(TOKEN); } -} \ No newline at end of file +} diff --git a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java index 8f2e916dd..7a62ed208 100644 --- a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java +++ b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java @@ -4,8 +4,10 @@ import java.io.IOException; import java.util.List; +import java.util.Optional; import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.core.HttpHeaders; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,27 +34,38 @@ public OAuth2AuthenticationProvider(String name, @Override public void filter(ClientRequestContext requestContext) throws IOException { - String bearerToken; + String bearerToken = ""; if (this.isTokenPropagation()) { bearerToken = this.getTokenForPropagation(requestContext.getHeaders()); + if (isEmptyOrBlank(bearerToken)) { + LOGGER.debug( + "Token propagation for OAUTH2 is enabled but the configured propagation header defined by {} is not present", + getHeaderForPropagation(getOpenApiSpecId(), getName())); + } } else { - delegate.filter(requestContext); - bearerToken = this.getCredentialsProvider().getOauth2BearerToken(CredentialsContext.builder() - .requestContext(requestContext) - .openApiSpecId(getOpenApiSpecId()) - .authName(getName()) - .build()); + Optional optionalBearerToken = this.getCredentialsProvider() + .getOauth2BearerToken(CredentialsContext.builder() + .requestContext(requestContext) + .openApiSpecId(getOpenApiSpecId()) + .authName(getName()) + .build()); + if (optionalBearerToken.isPresent()) { + bearerToken = optionalBearerToken.get(); + if (isEmptyOrBlank(bearerToken)) { + LOGGER.debug("The CredentialProvider implementation returned an empty OAUTH2 bearer"); + } + } else { + LOGGER.debug( + "There is no custom CredentialProvider implementation, the {} header will be set using delegate's filter. ", + HttpHeaders.AUTHORIZATION); + delegate.filter(requestContext); + } } if (!isEmptyOrBlank(bearerToken)) { addAuthorizationHeader(requestContext.getHeaders(), AuthUtils.authTokenOrBearer("Bearer", AbstractAuthProvider.sanitizeBearerToken(bearerToken))); - } else { - LOGGER.debug("No bearer token was found for the oauth2 security scheme: {}." + - " You must verify that a Quarkus OIDC Client with the name: {} is properly configured," + - " or the request header: {} is set when the token propagation is enabled.", - getName(), getName(), getHeaderForPropagation(getOpenApiSpecId(), getName())); } } 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 3cf740ba2..d3833089f 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 @@ -11,6 +11,8 @@ 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.OpenApiGeneratorException; @@ -23,6 +25,8 @@ public class ApiKeyAuthenticationProvider extends AbstractAuthProvider { private final ApiKeyIn apiKeyIn; private final String apiKeyName; + private static final Logger LOGGER = LoggerFactory.getLogger(ApiKeyAuthenticationProvider.class); + public ApiKeyAuthenticationProvider(final String openApiSpecId, final String name, final ApiKeyIn apiKeyIn, final String apiKeyName, List operations, CredentialsProvider credentialsProvider) { super(name, openApiSpecId, operations, credentialsProvider); @@ -54,11 +58,20 @@ && isUseAuthorizationHeaderValue()) { } private String getApiKey(ClientRequestContext requestContext) { - return credentialsProvider.getApiKey(CredentialsContext.builder() + final String key = credentialsProvider.getApiKey(CredentialsContext.builder() .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) - .build()); + .build()).orElse(""); + + if (key.isEmpty()) { + LOGGER.warn("configured {} property (see application.properties) is empty. hint: configure it.", + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(ConfigCredentialsProvider.API_KEY, + getOpenApiSpecId(), + getName())); + } + + return key; } private boolean isUseAuthorizationHeaderValue() { 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 6b25671c5..f39622bff 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 @@ -29,7 +29,7 @@ private String getUsername(ClientRequestContext requestContext) { .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) - .build()); + .build()).orElse(""); } private String getPassword(ClientRequestContext requestContext) { @@ -37,7 +37,7 @@ private String getPassword(ClientRequestContext requestContext) { .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) - .build()); + .build()).orElse(""); } @Override 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 12a1e9af4..91742cc16 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 @@ -51,6 +51,6 @@ private String getBearerToken(ClientRequestContext requestContext) { .requestContext(requestContext) .openApiSpecId(getOpenApiSpecId()) .authName(getName()) - .build()); + .build()).orElse(""); } } diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java index 00ee1e142..d89ee5240 100644 --- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java +++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java @@ -1,9 +1,10 @@ package io.quarkiverse.openapi.generator.providers; +import java.util.Optional; + import jakarta.annotation.Priority; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Alternative; -import jakarta.ws.rs.core.HttpHeaders; import org.eclipse.microprofile.config.ConfigProvider; import org.slf4j.Logger; @@ -26,53 +27,44 @@ public ConfigCredentialsProvider() { } @Override - public String getApiKey(CredentialsContext input) { - final String key = ConfigProvider.getConfig() + public Optional getApiKey(CredentialsContext input) { + return ConfigProvider.getConfig() .getOptionalValue( AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, input.getOpenApiSpecId(), input.getAuthName()), - String.class) - .orElse(""); - if (key.isEmpty()) { - LOGGER.warn("configured {} property (see application.properties) is empty. hint: configure it.", - AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, input.getOpenApiSpecId(), - input.getAuthName())); - } - return key; + String.class); + } @Override - public String getBasicUsername(CredentialsContext input) { + public Optional getBasicUsername(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( AbstractAuthProvider.getCanonicalAuthConfigPropertyName(USER_NAME, input.getOpenApiSpecId(), input.getAuthName()), - String.class) - .orElse(""); + String.class); } @Override - public String getBasicPassword(CredentialsContext input) { + public Optional getBasicPassword(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( AbstractAuthProvider.getCanonicalAuthConfigPropertyName(PASSWORD, input.getOpenApiSpecId(), input.getAuthName()), - String.class) - .orElse(""); + String.class); } @Override - public String getBearerToken(CredentialsContext input) { + public Optional getBearerToken(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( AbstractAuthProvider.getCanonicalAuthConfigPropertyName(BEARER_TOKEN, input.getOpenApiSpecId(), input.getAuthName()), - String.class) - .orElse(""); + String.class); } @Override - public String getOauth2BearerToken(CredentialsContext input) { - return input.getRequestContext().getHeaderString(HttpHeaders.AUTHORIZATION); + public Optional getOauth2BearerToken(CredentialsContext input) { + return Optional.empty(); } } diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java index 83d15a74d..6d6f13a10 100644 --- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java +++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/CredentialsProvider.java @@ -1,5 +1,7 @@ package io.quarkiverse.openapi.generator.providers; +import java.util.Optional; + /** * Provider for security credentials. Clients can implement this interface to control how to provide security credentials in * runtime. @@ -13,7 +15,7 @@ public interface CredentialsProvider { * @param input the input data available to the method * @return the API Key to use when filtering the request */ - String getApiKey(CredentialsContext input); + Optional getApiKey(CredentialsContext input); /** * Gets the username given the OpenAPI definition and security schema @@ -21,7 +23,7 @@ public interface CredentialsProvider { * @param input the input data available to the method * @return the username to use when filtering the request */ - String getBasicUsername(CredentialsContext input); + Optional getBasicUsername(CredentialsContext input); /** * Gets the password given the OpenAPI definition and security schema @@ -29,7 +31,7 @@ public interface CredentialsProvider { * @param input the input data available to the method * @return the password to use when filtering the request */ - String getBasicPassword(CredentialsContext input); + Optional getBasicPassword(CredentialsContext input); /** * Gets the Bearer Token given the OpenAPI definition and security schema @@ -37,7 +39,7 @@ public interface CredentialsProvider { * @param input the input data available to the method * @return the Bearer Token to use when filtering the request */ - String getBearerToken(CredentialsContext input); + Optional getBearerToken(CredentialsContext input); /** * Gets the OAuth2 Bearer Token given the OpenAPI definition and security schema @@ -45,5 +47,5 @@ public interface CredentialsProvider { * @param input the input data available to the method * @return the Bearer Token to use when filtering the request */ - String getOauth2BearerToken(CredentialsContext input); + Optional getOauth2BearerToken(CredentialsContext input); } From 480ce7747a723c157c91960ee61421abc68f6df6 Mon Sep 17 00:00:00 2001 From: Francisco Javier Tirado Sarti <65240126+fjtirado@users.noreply.github.com> Date: Wed, 18 Jun 2025 17:29:55 +0200 Subject: [PATCH 7/8] [Fix #1205] Making easier inheriting from ConfigCredentialsProvider (#1206) --- .../providers/ConfigCredentialsProvider.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java index d89ee5240..294017c97 100644 --- a/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java +++ b/client/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ConfigCredentialsProvider.java @@ -7,8 +7,6 @@ import jakarta.enterprise.inject.Alternative; import org.eclipse.microprofile.config.ConfigProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; @Dependent @Alternative @@ -20,17 +18,11 @@ public class ConfigCredentialsProvider implements CredentialsProvider { static final String BEARER_TOKEN = "bearer-token"; static final String API_KEY = "api-key"; - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCredentialsProvider.class); - - public ConfigCredentialsProvider() { - - } - @Override public Optional getApiKey(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( - AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, input.getOpenApiSpecId(), + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(API_KEY, getConfigKey(input), input.getAuthName()), String.class); @@ -40,7 +32,7 @@ public Optional getApiKey(CredentialsContext input) { public Optional getBasicUsername(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( - AbstractAuthProvider.getCanonicalAuthConfigPropertyName(USER_NAME, input.getOpenApiSpecId(), + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(USER_NAME, getConfigKey(input), input.getAuthName()), String.class); } @@ -49,7 +41,7 @@ public Optional getBasicUsername(CredentialsContext input) { public Optional getBasicPassword(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( - AbstractAuthProvider.getCanonicalAuthConfigPropertyName(PASSWORD, input.getOpenApiSpecId(), + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(PASSWORD, getConfigKey(input), input.getAuthName()), String.class); } @@ -58,11 +50,15 @@ public Optional getBasicPassword(CredentialsContext input) { public Optional getBearerToken(CredentialsContext input) { return ConfigProvider.getConfig() .getOptionalValue( - AbstractAuthProvider.getCanonicalAuthConfigPropertyName(BEARER_TOKEN, input.getOpenApiSpecId(), + AbstractAuthProvider.getCanonicalAuthConfigPropertyName(BEARER_TOKEN, getConfigKey(input), input.getAuthName()), String.class); } + protected String getConfigKey(CredentialsContext input) { + return input.getOpenApiSpecId(); + } + @Override public Optional getOauth2BearerToken(CredentialsContext input) { return Optional.empty(); From 8c19ff50fd3da380b5a68c47f61e9cd4f6c976f9 Mon Sep 17 00:00:00 2001 From: Ricardo Zanini Date: Wed, 18 Jun 2025 13:00:48 -0400 Subject: [PATCH 8/8] Adding 3.0.0-lts-SNAPSHOT to auth-provider new IT Signed-off-by: Ricardo Zanini --- client/integration-tests/auth-provider/pom.xml | 2 +- .../oidc/providers/OAuth2AuthenticationProvider.java | 6 +++--- .../openapi/generator/providers/AbstractAuthProvider.java | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/client/integration-tests/auth-provider/pom.xml b/client/integration-tests/auth-provider/pom.xml index 8a0bddcc2..84a493979 100644 --- a/client/integration-tests/auth-provider/pom.xml +++ b/client/integration-tests/auth-provider/pom.xml @@ -3,7 +3,7 @@ quarkus-openapi-generator-integration-tests io.quarkiverse.openapi.generator - 3.0.0-SNAPSHOT + 3.0.0-lts-SNAPSHOT 4.0.0 diff --git a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java index 7a62ed208..676f77876 100644 --- a/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java +++ b/client/oidc/src/main/java/io/quarkiverse/openapi/generator/oidc/providers/OAuth2AuthenticationProvider.java @@ -25,8 +25,8 @@ public class OAuth2AuthenticationProvider extends AbstractAuthProvider { private final OidcClientRequestFilterDelegate delegate; public OAuth2AuthenticationProvider(String name, - String openApiSpecId, OidcClientRequestFilterDelegate delegate, List operations, - CredentialsProvider credentialsProvider) { + String openApiSpecId, OidcClientRequestFilterDelegate delegate, List operations, + CredentialsProvider credentialsProvider) { super(name, openApiSpecId, operations, credentialsProvider); this.delegate = delegate; validateConfig(); @@ -72,7 +72,7 @@ public void filter(ClientRequestContext requestContext) throws IOException { private void validateConfig() { if (isTokenPropagation()) { LOGGER.warn("Token propagation was enabled for a the oauth2: {} securityScheme in the specification file: {}. " + - "This configuration can be done by using the property: {} and is not necessary a problem if the configuration is intentional.", + "This configuration can be done by using the property: {} and is not necessary a problem if the configuration is intentional.", getName(), getOpenApiSpecId(), getCanonicalAuthConfigPropertyName(TOKEN_PROPAGATION)); } } 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 a08a191ac..cc4acd5d9 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 @@ -8,7 +8,6 @@ import java.util.List; import java.util.Objects; -import io.vertx.codegen.doc.Token; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MultivaluedMap; @@ -31,7 +30,7 @@ public abstract class AbstractAuthProvider implements AuthProvider { private final List applyToOperations = new ArrayList<>(); protected AbstractAuthProvider(String name, String openApiSpecId, List operations, - CredentialsProvider credentialsProvider) { + CredentialsProvider credentialsProvider) { this.name = name; this.openApiSpecId = openApiSpecId; this.applyToOperations.addAll(operations); @@ -117,7 +116,6 @@ public CredentialsProvider getCredentialsProvider() { return credentialsProvider; } - protected void addAuthorizationHeader(MultivaluedMap headers, String value) { headers.put(HttpHeaders.AUTHORIZATION, Collections.singletonList(value)); } @@ -125,4 +123,4 @@ protected void addAuthorizationHeader(MultivaluedMap headers, St protected static boolean isEmptyOrBlank(String value) { return value == null || value.isBlank(); } -} \ No newline at end of file +}