Skip to content

Commit

Permalink
Fix API key cookie authentication (#568) (#569)
Browse files Browse the repository at this point in the history
* Fix API key cookie authentication (#568)

* Add integration test for key cookie authentication

* Apply review changes

* Add new integration maven module

* Apply suggested changes (hopefully) fixing IT

Co-authored-by: nmirasch <[email protected]>

* removed the final to avoid the 'Confusing overloading of methods'

Co-authored-by: nmirasch <[email protected]>

---------

Co-authored-by: nmirasch <[email protected]>
Co-authored-by: Ricardo Zanini <[email protected]>
  • Loading branch information
3 people authored Jan 19, 2024
1 parent b47f3c2 commit ed66066
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 10 deletions.
99 changes: 99 additions & 0 deletions integration-tests/cookie-authentication/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-openapi-generator-integration-tests</artifactId>
<groupId>io.quarkiverse.openapi.generator</groupId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-openapi-generator-it-cookie-authentication</artifactId>
<name>Quarkus - Openapi Generator - Integration Tests - Cookie Authentication</name>
<description>Use cookie authentication</description>

<dependencies>
<dependency>
<groupId>io.quarkiverse.openapi.generator</groupId>
<artifactId>quarkus-openapi-generator</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native-image</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${native.surefire.skip}</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<native.image.path>
${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager
</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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")));
}
}
Original file line number Diff line number Diff line change
@@ -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<String, String> 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();
}
}
}
1 change: 1 addition & 0 deletions integration-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<module>beanparam</module>
<module>change-directory</module>
<module>circuit-breaker</module>
<module>cookie-authentication</module>
<module>custom-templates</module>
<module>enum-property</module>
<module>exclude</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -87,16 +91,36 @@ void filterQueryCase() throws IOException {
}

@Test
void filterCookieCase() throws IOException {
Map<String, Cookie> cookies = new HashMap<>();
doReturn(cookies).when(requestContext).getCookies();
void filterCookieCaseEmpty() throws IOException {
final MultivaluedMap<String, Object> 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<Object> 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<String, Object> 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<Object> cookies = headers.get(HttpHeaders.COOKIE);
assertThat(cookies)
.satisfiesExactlyInAnyOrder(
cookie -> assertCookie(cookie, existingCookieName, existingCookieValue),
cookie -> assertCookie(cookie, API_KEY_NAME, API_KEY_VALUE));
}

@Test
Expand All @@ -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));
}
}

0 comments on commit ed66066

Please sign in to comment.