diff --git a/core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java b/core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
index cb6e2f054e..de4bc97fd5 100644
--- a/core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
+++ b/core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
@@ -75,8 +75,7 @@ private static void start(String[] args) {
if (commandLine.getCommand().getName().equals("private-jwk-to-public")) {
privateJwkToPublic(commandLine);
}
- var router = getRouter(commandLine);
- if (router instanceof DefaultRouter dr)
+ if (getRouter(commandLine) instanceof DefaultRouter dr)
dr.waitFor();
}
diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/ApiKeysInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/ApiKeysInterceptor.java
index d6cc29902e..c598b02ce6 100644
--- a/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/ApiKeysInterceptor.java
+++ b/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/ApiKeysInterceptor.java
@@ -14,7 +14,6 @@
package com.predic8.membrane.core.interceptor.apikey;
import com.predic8.membrane.annot.*;
-import com.predic8.membrane.core.config.spring.*;
import com.predic8.membrane.core.exchange.*;
import com.predic8.membrane.core.interceptor.*;
import com.predic8.membrane.core.interceptor.apikey.extractors.*;
@@ -23,11 +22,10 @@
import org.slf4j.*;
import java.util.*;
-import java.util.stream.*;
import static com.predic8.membrane.core.exceptions.ProblemDetails.*;
import static com.predic8.membrane.core.interceptor.Outcome.*;
-import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.*;
import static java.util.stream.Stream.*;
/**
@@ -85,10 +83,17 @@ public String getLongDescription() {
@Override
public void init() {
super.init();
- // At the moment the beanFactory is only there when the Membrane configuration was read from XML
+
+ // Todo: Move logic into the registry
+ // The beanFactory is only there when the Membrane configuration was read from XML
if (router.getBeanFactory() != null) {
stores.addAll(router.getBeanFactory().getBeansOfType(ApiKeyStore.class).values());
}
+ // For YAML configuration
+ if (router.getRegistry() != null) {
+ this.stores.addAll(router.getRegistry().getBeans(ApiKeyStore.class));
+ }
+
stores.forEach(s -> s.init(router));
// Add the default extractor if none is configured
diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/extractors/ApiKeyHeaderExtractor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/extractors/ApiKeyHeaderExtractor.java
index 1f2a82bd94..26b3c65315 100644
--- a/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/extractors/ApiKeyHeaderExtractor.java
+++ b/core/src/main/java/com/predic8/membrane/core/interceptor/apikey/extractors/ApiKeyHeaderExtractor.java
@@ -22,7 +22,6 @@
import static com.predic8.membrane.core.security.ApiKeySecurityScheme.In.*;
/**
- * @deprecated Set an expression like ${header['api']} on apiKey
* @description Extracts an API key from a specific HTTP request header. By default, the header name
* is X-Api-Key. If the header is present, its first value is returned as the API key.
*
diff --git a/distribution/examples/security/api-key/apikey-openapi/apis.yaml b/distribution/examples/security/api-key/apikey-openapi/apis.yaml new file mode 100644 index 0000000000..3227b1e5ee --- /dev/null +++ b/distribution/examples/security/api-key/apikey-openapi/apis.yaml @@ -0,0 +1,25 @@ +# yaml-language-server: $schema=https://www.membrane-api.io/v7.0.5.json + +components: + store: + apiKeyFileStore: + location: ./demo-keys.txt +--- + +api: + port: 2000 + specs: + - openapi: + location: fruitshop-api-v2-openapi-3-security.yml + validateSecurity: true + flow: + - apiKey: + # API keys are validated in the OpenAPI validator with validateSecurity: true. See the OpenAPI document for details. + required: false + extractors: + - headerExtractor: + name: "X-Api-Key" + # The API key must be extracted before the OpenAPI validator is called. + # Normally, the OpenAPI is validated before the flow is executed. By explicitly + # setting the openapiValidator to this position, the OpenAPI is validated after the apiKey plugin. + - openapiValidator: {} \ No newline at end of file diff --git a/distribution/src/test/java/com/predic8/membrane/examples/withinternet/test/APIKeyWithOpenAPIExampleTest.java b/distribution/src/test/java/com/predic8/membrane/examples/withinternet/test/APIKeyWithOpenAPIExampleTest.java index f51c2b045a..50bc4ee199 100644 --- a/distribution/src/test/java/com/predic8/membrane/examples/withinternet/test/APIKeyWithOpenAPIExampleTest.java +++ b/distribution/src/test/java/com/predic8/membrane/examples/withinternet/test/APIKeyWithOpenAPIExampleTest.java @@ -26,13 +26,15 @@ public class APIKeyWithOpenAPIExampleTest extends AbstractSampleMembraneStartStopTestcase { + public static final String API_KEY_HEADER = "X-Api-Key"; + @Override protected String getExampleDirName() { return "security/api-key/apikey-openapi"; } @Test - public void noApiKey() { + void noApiKey() { when() .get("http://localhost:2000/shop/v2/products") .then().assertThat() @@ -41,9 +43,9 @@ public void noApiKey() { } @Test - public void noScopesGet() { + void noScopesGet() { given() - .header("X-Api-Key", "111") + .header(API_KEY_HEADER, "111") .when() .get("http://localhost:2000/shop/v2/products") .then().assertThat() @@ -53,9 +55,9 @@ public void noScopesGet() { } @Test - public void noScopesPost() { + void noScopesPost() { given() - .header("X-Api-Key", "111") + .header(API_KEY_HEADER, "111") .contentType(APPLICATION_JSON) .body(""" { @@ -78,9 +80,9 @@ public void noScopesPost() { } @Test - public void writeScopes() { + void writeScopes() { given() - .headers("X-Api-Key", "222") + .headers(API_KEY_HEADER, "222") .contentType(APPLICATION_JSON) .body("{\"name\": \"Mango\", \"price\": 2.79}") .when()