Skip to content

Commit 3344031

Browse files
cschubertcsMatKuhr
andauthored
feat: Extend AuthToken Forwarding (#232)
Co-authored-by: Matthias Kuhr <52661546+MatKuhr@users.noreply.github.com>
1 parent 620d826 commit 3344031

File tree

4 files changed

+171
-16
lines changed

4 files changed

+171
-16
lines changed

cloudplatform/cloudplatform-connectivity/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ComplexDestinationPropertyFactory.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -184,28 +184,29 @@ AuthenticationType getAuthenticationType(
184184
@Nonnull final DestinationProperties baseProperties,
185185
@Nonnull final Option<BasicCredentials> basicCredentials )
186186
{
187-
final Option<AuthenticationType> authType =
187+
final AuthenticationType authType =
188188
baseProperties
189189
.get(DestinationProperty.AUTH_TYPE)
190-
.orElse(() -> baseProperties.get(DestinationProperty.AUTH_TYPE_FALLBACK));
190+
.orElse(() -> baseProperties.get(DestinationProperty.AUTH_TYPE_FALLBACK))
191+
.onEmpty(
192+
() -> log
193+
.debug(
194+
"No valid JSON primitive '{}' or '{}' defined. Falling back to {}.",
195+
DestinationProperty.AUTH_TYPE,
196+
DestinationProperty.AUTH_TYPE_FALLBACK,
197+
AuthenticationType.NO_AUTHENTICATION))
198+
.getOrElse(AuthenticationType.NO_AUTHENTICATION);
191199

192-
if( authType.isEmpty() ) {
193-
final AuthenticationType fallback;
200+
final boolean forwardAuthToken = baseProperties.get(DestinationProperty.FORWARD_AUTH_TOKEN).getOrElse(false);
194201

195-
if( basicCredentials.isDefined() ) {
196-
fallback = AuthenticationType.BASIC_AUTHENTICATION;
197-
} else if( baseProperties.get(DestinationProperty.FORWARD_AUTH_TOKEN).getOrElse(false) ) {
198-
fallback = AuthenticationType.TOKEN_FORWARDING;
199-
} else {
200-
fallback = AuthenticationType.NO_AUTHENTICATION;
201-
}
202-
203-
final String msg = "No valid JSON primitive '{}' or '{}' defined. Falling back to {}.";
204-
log.debug(msg, DestinationProperty.AUTH_TYPE, DestinationProperty.AUTH_TYPE_FALLBACK, fallback);
202+
if( authType == AuthenticationType.NO_AUTHENTICATION && basicCredentials.isDefined() ) {
203+
return AuthenticationType.BASIC_AUTHENTICATION;
204+
}
205205

206-
return fallback;
206+
if( authType == AuthenticationType.NO_AUTHENTICATION && forwardAuthToken ) {
207+
return AuthenticationType.TOKEN_FORWARDING;
207208
}
208-
return authType.get();
209+
return authType;
209210
}
210211

211212
@Nonnull

cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceFactoryTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,17 @@ void testTokenErrorsAreThrown()
121121
.isInstanceOf(DestinationAccessException.class)
122122
.hasMessageContaining("some-error-message");
123123
}
124+
125+
@Test
126+
void propertyForwardAuthTokenShouldSetAuthenticationType()
127+
{
128+
response.getDestinationConfiguration().put("Type", "HTTP");
129+
response.getDestinationConfiguration().put("Name", "httpDestination");
130+
response.getDestinationConfiguration().put("URL", "https://example.com");
131+
response.getDestinationConfiguration().put("forwardAuthToken", "true");
132+
133+
final Destination result = DestinationServiceFactory.fromDestinationServiceV1Response(response);
134+
135+
assertThat(result.asHttp().getAuthenticationType()).isEqualTo(AuthenticationType.TOKEN_FORWARDING);
136+
}
124137
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package com.sap.cloud.sdk.cloudplatform.connectivity;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import java.util.Collection;
6+
import java.util.HashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.function.Consumer;
10+
11+
import javax.annotation.Nonnull;
12+
13+
import org.junit.jupiter.params.ParameterizedTest;
14+
import org.junit.jupiter.params.provider.MethodSource;
15+
16+
import com.google.common.net.HttpHeaders;
17+
import com.sap.cloud.sdk.cloudplatform.requestheader.RequestHeaderAccessor;
18+
19+
class ForwardAuthTokenTest
20+
{
21+
static Collection<TestCase> createTestCases()
22+
{
23+
return List
24+
.of(
25+
// forwardAuthToken = true && authType = NoAuthentication
26+
TestCaseBuilder
27+
.forProperty(DestinationProperty.FORWARD_AUTH_TOKEN.getKeyName(), "true")
28+
.and(DestinationProperty.AUTH_TYPE.getKeyName(), AuthenticationType.NO_AUTHENTICATION)
29+
.expectTokenForwarding(),
30+
// forwardAuthToken = true && unset authType
31+
TestCaseBuilder
32+
.forProperty(DestinationProperty.FORWARD_AUTH_TOKEN.getKeyName(), "true")
33+
.expectTokenForwarding(),
34+
// forwardAuthToken = false && authType = NoAuthentication
35+
TestCaseBuilder
36+
.forProperty(DestinationProperty.FORWARD_AUTH_TOKEN.getKeyName(), "false")
37+
.and(DestinationProperty.AUTH_TYPE.getKeyName(), AuthenticationType.NO_AUTHENTICATION)
38+
.expectNoTokenForwarding(),
39+
// forwardAuthToken = false && unset authType
40+
TestCaseBuilder
41+
.forProperty(DestinationProperty.FORWARD_AUTH_TOKEN.getKeyName(), "false")
42+
.expectNoTokenForwarding(),
43+
// unset forwardAuthToken && authType = NoAuthentication
44+
TestCaseBuilder
45+
.forProperty(DestinationProperty.AUTH_TYPE.getKeyName(), AuthenticationType.NO_AUTHENTICATION)
46+
.expectNoTokenForwarding(),
47+
// unset forwardAuthToken && unset authType
48+
TestCaseBuilder.forNoProperties().expectNoTokenForwarding());
49+
}
50+
51+
private enum AssertionType
52+
{
53+
TOKEN_IS_FORWARDED(ForwardAuthTokenTest::assertThatTokenIsForwarded),
54+
TOKEN_IS_NOT_FORWARDED(ForwardAuthTokenTest::assertThatTokenIsNotForwarded);
55+
56+
private final Consumer<HttpDestination> assertion;
57+
58+
AssertionType( final Consumer<HttpDestination> assertion )
59+
{
60+
this.assertion = assertion;
61+
}
62+
}
63+
64+
private record TestCase( Map<String, Object> properties, AssertionType forwardingAssertion )
65+
{
66+
}
67+
68+
private static class TestCaseBuilder
69+
{
70+
71+
private final Map<String, Object> properties = new HashMap<>();
72+
73+
TestCaseBuilder( String key, Object value )
74+
{
75+
properties.put(key, value);
76+
}
77+
78+
TestCaseBuilder()
79+
{
80+
81+
}
82+
83+
static TestCaseBuilder forProperty( String key, Object value )
84+
{
85+
return new TestCaseBuilder(key, value);
86+
}
87+
88+
static TestCaseBuilder forNoProperties()
89+
{
90+
return new TestCaseBuilder();
91+
}
92+
93+
TestCaseBuilder and( final String key, final Object value )
94+
{
95+
properties.put(key, value);
96+
return this;
97+
}
98+
99+
TestCase expectTokenForwarding()
100+
{
101+
return new TestCase(properties, AssertionType.TOKEN_IS_FORWARDED);
102+
}
103+
104+
TestCase expectNoTokenForwarding()
105+
{
106+
return new TestCase(properties, AssertionType.TOKEN_IS_NOT_FORWARDED);
107+
}
108+
}
109+
110+
@ParameterizedTest
111+
@MethodSource( "createTestCases" )
112+
void localDestinationShouldFulfillTestCase( @Nonnull final TestCase testCase )
113+
{
114+
final HttpDestination destination = buildLocalDestination(testCase.properties);
115+
testCase.forwardingAssertion.assertion.accept(destination);
116+
}
117+
118+
private HttpDestination buildLocalDestination( Map<String, Object> properties )
119+
{
120+
return DefaultDestination.fromMap(properties).uri("sap.com").build().asHttp();
121+
}
122+
123+
private static void assertThatTokenIsNotForwarded( final HttpDestination destination )
124+
{
125+
final Collection<Header> headers =
126+
RequestHeaderAccessor
127+
.executeWithHeaderContainer(Map.of(HttpHeaders.AUTHORIZATION, "token"), () -> destination.getHeaders());
128+
129+
assertThat(headers).isEmpty();
130+
}
131+
132+
private static void assertThatTokenIsForwarded( final HttpDestination destination )
133+
{
134+
final Collection<Header> headers =
135+
RequestHeaderAccessor
136+
.executeWithHeaderContainer(Map.of(HttpHeaders.AUTHORIZATION, "token"), () -> destination.getHeaders());
137+
138+
assertThat(headers).containsExactly(new Header(HttpHeaders.AUTHORIZATION, "token"));
139+
}
140+
}

release_notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
- Update [Guava](https://central.sonatype.com/artifact/com.google.guava/guava/33.0.0-jre) from `32.1.3-jre` to `33.0.0-jre`
5555
- Update [Jackson](https://central.sonatype.com/artifact/com.fasterxml.jackson.core/jackson-core/2.16.1) from `2.15.3` to `2.16.1`
5656
- Update [Commons Lang](https://central.sonatype.com/artifact/org.apache.commons/commons-lang3/3.14.0) from `3.13.0` to `3.14.0`
57+
- Destinations retrieved from the BTP Destination Service now correctly evaluate the `forwardAuthToken` property if it has the authentication type `NoAuthentication`.
5758

5859
### 🐛 Fixed Issues
5960

0 commit comments

Comments
 (0)