Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix API key cookie authentication (#568) #569

Merged
merged 6 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(final 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));
}
}