diff --git a/integration-tests/cookie-authentication/pom.xml b/integration-tests/cookie-authentication/pom.xml new file mode 100644 index 00000000..52fa2111 --- /dev/null +++ b/integration-tests/cookie-authentication/pom.xml @@ -0,0 +1,99 @@ + + + + quarkus-openapi-generator-integration-tests + io.quarkiverse.openapi.generator + 3.0.0-SNAPSHOT + + 4.0.0 + + quarkus-openapi-generator-it-cookie-authentication + Quarkus - Openapi Generator - Integration Tests - Cookie Authentication + Use cookie authentication + + + + io.quarkiverse.openapi.generator + quarkus-openapi-generator + + + org.assertj + assertj-core + test + + + io.quarkus + quarkus-junit5 + test + + + + com.github.tomakehurst + wiremock-jre8 + 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 + + + + diff --git a/integration-tests/cookie-authentication/src/main/openapi/cookie-authentication.json b/integration-tests/cookie-authentication/src/main/openapi/cookie-authentication.json new file mode 100644 index 00000000..e926a928 --- /dev/null +++ b/integration-tests/cookie-authentication/src/main/openapi/cookie-authentication.json @@ -0,0 +1,46 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Quarkus - Openapi Generator - Integration Tests - Cookie Authentication", + "version": "v1" + }, + "servers": [ + { + "url": "http://localhost:8080" + } + ], + "security": [ + { + "cookie": [] + } + ], + "tags": [ + { + "name": "Test" + } + ], + "paths": { + "/v1/test": { + "get": { + "tags": [ + "Test" + ], + "operationId": "doTest", + "responses": { + "204": { + "description": "Test succeeded" + } + } + } + } + }, + "components": { + "securitySchemes": { + "cookie": { + "type": "apiKey", + "name": "TASKLIST-SESSION", + "in": "cookie" + } + } + } +} diff --git a/integration-tests/cookie-authentication/src/main/resources/application.properties b/integration-tests/cookie-authentication/src/main/resources/application.properties new file mode 100644 index 00000000..517251c0 --- /dev/null +++ b/integration-tests/cookie-authentication/src/main/resources/application.properties @@ -0,0 +1,2 @@ +quarkus.openapi-generator.codegen.spec.cookie_authentication_json.mutiny=true +quarkus.openapi-generator.cookie_authentication_json.auth.cookie.api-key=Quarkus diff --git a/integration-tests/cookie-authentication/src/test/java/io/quarkiverse/openapi/generator/it/CookieAuthenticationTest.java b/integration-tests/cookie-authentication/src/test/java/io/quarkiverse/openapi/generator/it/CookieAuthenticationTest.java new file mode 100644 index 00000000..eb53e89f --- /dev/null +++ b/integration-tests/cookie-authentication/src/test/java/io/quarkiverse/openapi/generator/it/CookieAuthenticationTest.java @@ -0,0 +1,43 @@ +package io.quarkiverse.openapi.generator.it; + +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; + +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Response; + +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.openapi.quarkus.cookie_authentication_json.api.TestApi; + +import com.github.tomakehurst.wiremock.WireMockServer; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +@QuarkusTestResource(WiremockCookieAuthentication.class) +@Tag("resteasy-reactive") +class CookieAuthenticationTest { + // Injected by Quarkus test resource + WireMockServer wireMockServer; + + @RestClient + @Inject + TestApi testApi; + + @Test + void apiIsBeingGenerated() { + final Response response = testApi.doTest() + .await() + .atMost(Duration.ofSeconds(5L)); + assertThat(response) + .extracting(Response::getStatus) + .isEqualTo(204); + wireMockServer.verify(getRequestedFor(urlEqualTo("/v1/test"))); + } +} diff --git a/integration-tests/cookie-authentication/src/test/java/io/quarkiverse/openapi/generator/it/WiremockCookieAuthentication.java b/integration-tests/cookie-authentication/src/test/java/io/quarkiverse/openapi/generator/it/WiremockCookieAuthentication.java new file mode 100644 index 00000000..321ab06a --- /dev/null +++ b/integration-tests/cookie-authentication/src/test/java/io/quarkiverse/openapi/generator/it/WiremockCookieAuthentication.java @@ -0,0 +1,41 @@ +package io.quarkiverse.openapi.generator.it; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; + +import java.util.Map; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; + +public class WiremockCookieAuthentication implements QuarkusTestResourceLifecycleManager { + private static final String URL_KEY = "quarkus.rest-client.cookie_authentication_json.url"; + + private WireMockServer wireMockServer; + + @Override + public Map start() { + wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort()); + wireMockServer.start(); + + wireMockServer.stubFor(get(urlPathEqualTo("/v1/test")) + .willReturn(aResponse().withStatus(204))); + + return Map.of(URL_KEY, wireMockServer.baseUrl()); + } + + @Override + public void inject(TestInjector testInjector) { + testInjector.injectIntoFields(wireMockServer, f -> f.getName().equals("wireMockServer")); + } + + @Override + public void stop() { + if (wireMockServer != null) { + wireMockServer.stop(); + } + } +} diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 870fb57c..95172fd4 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -14,6 +14,7 @@ beanparam change-directory circuit-breaker + cookie-authentication custom-templates enum-property exclude diff --git a/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java b/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java index 56bed1ea..e949fb3f 100644 --- a/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java +++ b/runtime/src/main/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProvider.java @@ -6,6 +6,7 @@ import jakarta.ws.rs.client.ClientRequestContext; import jakarta.ws.rs.core.Cookie; +import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.UriBuilder; import org.slf4j.Logger; @@ -44,7 +45,7 @@ public void filter(ClientRequestContext requestContext) throws IOException { requestContext.setUri(UriBuilder.fromUri(requestContext.getUri()).queryParam(apiKeyName, getApiKey()).build()); break; case cookie: - requestContext.getCookies().put(apiKeyName, new Cookie.Builder(apiKeyName).value(getApiKey()).build()); + requestContext.getHeaders().add(HttpHeaders.COOKIE, new Cookie.Builder(apiKeyName).value(getApiKey()).build()); break; case header: if (requestContext.getHeaderString("Authorization") != null diff --git a/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProviderTest.java b/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProviderTest.java index f7417c62..992cf65d 100644 --- a/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProviderTest.java +++ b/runtime/src/test/java/io/quarkiverse/openapi/generator/providers/ApiKeyAuthenticationProviderTest.java @@ -7,12 +7,16 @@ import java.io.IOException; import java.net.URI; -import java.util.HashMap; -import java.util.Map; +import java.util.List; +import java.util.Objects; import java.util.Optional; import jakarta.ws.rs.core.Cookie; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MultivaluedMap; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.jboss.resteasy.specimpl.MultivaluedTreeMap; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; @@ -87,16 +91,36 @@ void filterQueryCase() throws IOException { } @Test - void filterCookieCase() throws IOException { - Map cookies = new HashMap<>(); - doReturn(cookies).when(requestContext).getCookies(); + void filterCookieCaseEmpty() throws IOException { + final MultivaluedMap headers = new MultivaluedTreeMap<>(); + doReturn(headers).when(requestContext).getHeaders(); provider = new ApiKeyAuthenticationProvider(OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME, ApiKeyIn.cookie, API_KEY_NAME, generatorConfig); provider.filter(requestContext); - Cookie cookie = cookies.get(API_KEY_NAME); - assertThat(cookie).isNotNull(); - assertThat(cookie.getName()).isEqualTo(API_KEY_NAME); - assertThat(cookie.getValue()).isEqualTo(API_KEY_VALUE); + final List cookies = headers.get(HttpHeaders.COOKIE); + assertThat(cookies) + .singleElement() + .satisfies(cookie -> assertCookie(cookie, API_KEY_NAME, API_KEY_VALUE)); + } + + @Test + void filterCookieCaseExisting() throws IOException { + final MultivaluedMap headers = new MultivaluedTreeMap<>(); + final String existingCookieName = "quarkus"; + final String existingCookieValue = "rocks"; + final Cookie existingCookie = new Cookie.Builder(existingCookieName) + .value(existingCookieValue) + .build(); + 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, + generatorConfig); + provider.filter(requestContext); + final List cookies = headers.get(HttpHeaders.COOKIE); + assertThat(cookies) + .satisfiesExactlyInAnyOrder( + cookie -> assertCookie(cookie, existingCookieName, existingCookieValue), + cookie -> assertCookie(cookie, API_KEY_NAME, API_KEY_VALUE)); } @Test @@ -107,4 +131,11 @@ void tokenPropagationNotSupported() { .hasMessageContaining("quarkus.openapi-generator.%s.auth.%s.token-propagation", OPEN_API_FILE_SPEC_ID, AUTH_SCHEME_NAME); } + + private void assertCookie(final Object cookie, final String name, final String value) { + assertThat(cookie) + .asInstanceOf(InstanceOfAssertFactories.type(Cookie.class)) + .matches(c -> Objects.equals(c.getName(), name)) + .matches(c -> Objects.equals(c.getValue(), value)); + } }