This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
The following commit(s) were added to refs/heads/main by this push:
new dd1f234326b CAMEL-25568: camel-platform-http-starter - test that
camel-oauth reads the request of the platform-http message (#2037)
dd1f234326b is described below
commit dd1f234326b29f3072030ae493731002727c7ba6
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Oct 15 15:21:39 2026 +0200
CAMEL-25568: camel-platform-http-starter - test that camel-oauth reads the
request of the platform-http message (#2037)
camel-oauth recognises the platform-http message of Spring Boot by its
class name and reads the bearer token from its request. Test it behind
the real consumer, so that a rename of PlatformHttpMessage, or a message
that no longer gives the request, is caught here.
Signed-off-by: Andrea Cosentino <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../camel-platform-http-starter/pom.xml | 7 +
...SpringBootPlatformHttpOAuthBearerTokenTest.java | 181 +++++++++++++++++++++
2 files changed, 188 insertions(+)
diff --git a/components-starter/camel-platform-http-starter/pom.xml
b/components-starter/camel-platform-http-starter/pom.xml
index 3748536815f..f5618d142ae 100644
--- a/components-starter/camel-platform-http-starter/pom.xml
+++ b/components-starter/camel-platform-http-starter/pom.xml
@@ -89,6 +89,13 @@
<version>${rest-assured-version}</version>
<scope>test</scope>
</dependency>
+ <!-- camel-oauth reads the request headers of the platform-http message -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-oauth</artifactId>
+ <version>${camel-version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpOAuthBearerTokenTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpOAuthBearerTokenTest.java
new file mode 100644
index 00000000000..1c14bce27d4
--- /dev/null
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpOAuthBearerTokenTest.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.platform.http.springboot;
+
+import com.google.gson.JsonObject;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.oauth.Credentials;
+import org.apache.camel.oauth.OAuth;
+import org.apache.camel.oauth.OAuthBearerTokenProcessor;
+import org.apache.camel.oauth.OAuthCodeFlowParams;
+import org.apache.camel.oauth.OAuthException;
+import org.apache.camel.oauth.OAuthFactory;
+import org.apache.camel.oauth.OAuthLogoutParams;
+import org.apache.camel.oauth.TokenCredentials;
+import org.apache.camel.oauth.UserProfile;
+import org.apache.camel.oauth.jakarta.ServletOAuthFactory;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import
org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.SecurityFilterChain;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
+
+/**
+ * camel-oauth reads the bearer token from the request of the platform-http
message of Spring Boot
+ * ({@link PlatformHttpMessage}), which it matches by class name: these tests
fail if that class is renamed or no longer
+ * gives the request, because the token of a form parameter would then be read
from the message headers.
+ */
+@EnableAutoConfiguration
+@CamelSpringBootTest
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
+ SpringBootPlatformHttpOAuthBearerTokenTest.class,
SpringBootPlatformHttpOAuthBearerTokenTest.TestConfiguration.class,
+ PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class })
+class SpringBootPlatformHttpOAuthBearerTokenTest {
+
+ private static final String TOKEN = "alice-token";
+
+ @Autowired
+ private Environment env;
+
+ @BeforeEach
+ void setUp() {
+ RestAssured.port = env.getRequiredProperty("local.server.port",
Integer.class);
+ }
+
+ @Test
+ void bearerTokenIsReadFromTheAuthorizationHeader() {
+ given().header("Authorization", "Bearer " + TOKEN)
+ .get("/bearer")
+ .then().statusCode(200).body(equalTo("alice"));
+ }
+
+ @Test
+ void bearerTokenIsNotReadFromAFormParameter() {
+ given().contentType(ContentType.URLENC).formParam("Authorization",
"Bearer " + TOKEN)
+ .post("/bearer")
+ .then().statusCode(401);
+ }
+
+ @Test
+ void bearerTokenIsNotReadFromAQueryParameter() {
+ given().queryParam("Authorization", "Bearer " + TOKEN)
+ .get("/bearer")
+ .then().statusCode(401);
+ }
+
+ @Test
+ void requestIsFoundWhenTheRouteRemovedTheCamelHeaders() {
+ given().header("Authorization", "Bearer " + TOKEN)
+ .get("/bearer-without-camel-headers")
+ .then().statusCode(200).body(equalTo("alice"));
+ given().contentType(ContentType.URLENC).formParam("Authorization",
"Bearer " + TOKEN)
+ .post("/bearer-without-camel-headers")
+ .then().statusCode(401);
+ }
+
+ @Configuration
+ static class TestConfiguration {
+
+ @Bean
+ SecurityFilterChain securityFilterChain(HttpSecurity http) throws
Exception {
+ http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
+ .csrf(csrf -> csrf.disable());
+ return http.build();
+ }
+
+ // camel-oauth looks up its factory and its OAuth instance in the
registry by class name. Without a factory
+ // bean it looks for the platform-http router of Vert.x, whose class
is not on this classpath.
+ @Bean(name = "org.apache.camel.oauth.OAuthFactory")
+ OAuthFactory oauthFactory(CamelContext camelContext) {
+ return new ServletOAuthFactory(camelContext);
+ }
+
+ @Bean(name = "org.apache.camel.oauth.OAuth")
+ OAuth oauth() {
+ return new StubOAuth();
+ }
+
+ @Bean
+ RouteBuilder oauthBearerTokenRoutes() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("platform-http:/bearer")
+ .process(new OAuthBearerTokenProcessor())
+ .process(exchange ->
exchange.getMessage().setBody(subject(exchange)));
+ // as the security model advises for untrusted callers
+ from("platform-http:/bearer-without-camel-headers")
+ .removeHeaders("Camel*")
+ .process(new OAuthBearerTokenProcessor())
+ .process(exchange ->
exchange.getMessage().setBody(subject(exchange)));
+ }
+ };
+ }
+
+ private static String subject(Exchange exchange) {
+ return exchange.getProperty(OAuth.CAMEL_OAUTH_USER_PROFILE,
UserProfile.class).subject();
+ }
+ }
+
+ /**
+ * An identity provider stand-in that knows one access token.
+ */
+ static final class StubOAuth extends OAuth {
+
+ @Override
+ public void discoverOAuthConfig(CamelContext ctx) {
+ // nothing to discover
+ }
+
+ @Override
+ public UserProfile authenticate(Credentials creds) {
+ if (creds instanceof TokenCredentials tokenCreds &&
TOKEN.equals(tokenCreds.getToken())) {
+ var principal = new JsonObject();
+ principal.addProperty("access_token", TOKEN);
+ principal.addProperty("username", "alice");
+ var attributes = new JsonObject();
+ attributes.addProperty("exp", System.currentTimeMillis() /
1000L + 3600);
+ return new UserProfile(principal, attributes);
+ }
+ throw new OAuthException("Unknown token");
+ }
+
+ @Override
+ public String buildLogoutRequestUrl(OAuthLogoutParams params) {
+ return "https://idp.example/logout";
+ }
+
+ @Override
+ public String buildCodeFlowAuthRequestUrl(OAuthCodeFlowParams params) {
+ return "https://idp.example/auth";
+ }
+ }
+}