Skip to content

Commit 78c1f60

Browse files
authored
fix: DwC Auth Token not available (#337)
1 parent a9328d9 commit 78c1f60

File tree

9 files changed

+134
-4
lines changed

9 files changed

+134
-4
lines changed

cloudplatform/connectivity-dwc/pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@
6969
<groupId>org.slf4j</groupId>
7070
<artifactId>slf4j-api</artifactId>
7171
</dependency>
72+
<dependency>
73+
<groupId>com.auth0</groupId>
74+
<artifactId>java-jwt</artifactId>
75+
</dependency>
7276
<dependency>
7377
<groupId>org.slf4j</groupId>
7478
<artifactId>jcl-over-slf4j</artifactId>

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

+19
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ public class DwcHeaderUtils
3535
* The name of the header that contains the Deploy with Confidence scopes information.
3636
*/
3737
public static final String DWC_SUBDOMAIN_HEADER = "dwc-subdomain";
38+
/**
39+
* The name of the header that contains the Deploy with Confidence JWT token.
40+
*/
41+
public static final String DWC_JWT_HEADER = "dwc-jwt";
3842

3943
/**
4044
* This method fetches the value of the {@link #DWC_TENANT_HEADER} header or throws an
@@ -85,6 +89,21 @@ public static String getDwcPrincipalIdOrThrow()
8589
return logonName;
8690
}
8791

92+
/**
93+
* This method fetches the value of the {@link #DWC_JWT_HEADER} header or throws an
94+
* {@link DwcHeaderNotFoundException} if the header was not found.
95+
*
96+
* @return The value of the {@link #DWC_JWT_HEADER} header.
97+
* @throws DwcHeaderNotFoundException
98+
* if the header was not found.
99+
* @since 5.6.0
100+
*/
101+
@Nonnull
102+
public static String getDwcJwtOrThrow()
103+
{
104+
return getNonEmptyDwcHeaderValue(DWC_JWT_HEADER);
105+
}
106+
88107
@Nonnull
89108
private static String getNonEmptyDwcHeaderValue( @Nonnull final String key )
90109
throws DwcHeaderNotFoundException
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.sap.cloud.sdk.cloudplatform.security;
2+
3+
import javax.annotation.Nonnull;
4+
import javax.annotation.Nullable;
5+
6+
import com.auth0.jwt.JWT;
7+
import com.sap.cloud.sdk.cloudplatform.DwcHeaderUtils;
8+
import com.sap.cloud.sdk.cloudplatform.security.exception.AuthTokenAccessException;
9+
import com.sap.cloud.sdk.cloudplatform.thread.ThreadContext;
10+
import com.sap.cloud.sdk.cloudplatform.thread.ThreadContextAccessor;
11+
12+
import io.vavr.control.Try;
13+
14+
/**
15+
* Auth token facade for Deploy with Confidence (DwC) environment.
16+
*
17+
* @since 5.6.0
18+
*/
19+
public class DwcAuthTokenFacade extends DefaultAuthTokenFacade
20+
{
21+
private static final String AUTH_TOKEN = AuthTokenThreadContextListener.PROPERTY_AUTH_TOKEN;
22+
23+
@Nonnull
24+
@Override
25+
public Try<AuthToken> tryGetCurrentToken()
26+
{
27+
@Nullable
28+
final ThreadContext currentContext = ThreadContextAccessor.getCurrentContextOrNull();
29+
if( currentContext != null && currentContext.containsProperty(AUTH_TOKEN) ) {
30+
return currentContext.getPropertyValue(AUTH_TOKEN);
31+
}
32+
return Try.of(DwcAuthTokenFacade::extractAuthTokenFromDwcHeaders);
33+
}
34+
35+
@Nonnull
36+
private static AuthToken extractAuthTokenFromDwcHeaders()
37+
{
38+
try {
39+
final String token = DwcHeaderUtils.getDwcJwtOrThrow();
40+
return new AuthToken(JWT.decode(token));
41+
}
42+
catch( final Exception e ) {
43+
throw new AuthTokenAccessException("Failed to extract auth token from DwC headers.", e);
44+
}
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
com.sap.cloud.sdk.cloudplatform.security.DwcAuthTokenFacade
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.sap.cloud.sdk.cloudplatform.security;
2+
3+
import static com.sap.cloud.sdk.cloudplatform.DwcHeaderUtils.DWC_JWT_HEADER;
4+
import static org.assertj.core.api.Assertions.assertThat;
5+
6+
import java.util.Map;
7+
8+
import org.junit.jupiter.api.Test;
9+
10+
import com.auth0.jwt.JWT;
11+
import com.auth0.jwt.algorithms.Algorithm;
12+
import com.google.common.collect.ImmutableMap;
13+
import com.sap.cloud.sdk.cloudplatform.requestheader.RequestHeaderAccessor;
14+
import com.sap.cloud.sdk.cloudplatform.requestheader.RequestHeaderContainer;
15+
import com.sap.cloud.sdk.cloudplatform.security.exception.AuthTokenAccessException;
16+
import com.sap.cloud.sdk.cloudplatform.thread.ThreadContext;
17+
import com.sap.cloud.sdk.cloudplatform.thread.ThreadContextAccessor;
18+
19+
import io.vavr.control.Try;
20+
21+
class DwcAuthTokenFacadeTest
22+
{
23+
@Test
24+
void testFacadeIsPickedUpAutomatically()
25+
{
26+
assertThat(AuthTokenAccessor.getAuthTokenFacade()).isInstanceOf(DwcAuthTokenFacade.class);
27+
}
28+
29+
@Test
30+
void testSuccessfulAuthTokenRetrieval()
31+
{
32+
final String token = JWT.create().sign(Algorithm.none());
33+
34+
final AuthToken expectedToken = new AuthToken(JWT.decode(token));
35+
final Map<String, String> headers = ImmutableMap.of(DWC_JWT_HEADER, token);
36+
37+
RequestHeaderAccessor.executeWithHeaderContainer(headers, () -> {
38+
final ThreadContext currentContext = ThreadContextAccessor.getCurrentContext();
39+
final AuthToken currentToken = AuthTokenAccessor.getCurrentToken();
40+
final Try<AuthToken> maybeTokenFromContext =
41+
currentContext.getPropertyValue(AuthTokenThreadContextListener.PROPERTY_AUTH_TOKEN);
42+
43+
assertThat(currentToken).isEqualTo(expectedToken);
44+
assertThat(maybeTokenFromContext).contains(expectedToken);
45+
});
46+
}
47+
48+
@Test
49+
void testUnsuccessfulAuthTokenRetrieval()
50+
{
51+
RequestHeaderAccessor.executeWithHeaderContainer(RequestHeaderContainer.EMPTY, () -> {
52+
final ThreadContext currentContext = ThreadContextAccessor.getCurrentContext();
53+
final Try<AuthToken> authTokenFailure = AuthTokenAccessor.tryGetCurrentToken();
54+
final Try<AuthToken> shouldBeFailure =
55+
currentContext.getPropertyValue(AuthTokenThreadContextListener.PROPERTY_AUTH_TOKEN);
56+
57+
assertThat(authTokenFailure.isFailure()).isTrue();
58+
assertThat(authTokenFailure.getCause()).isInstanceOf(AuthTokenAccessException.class);
59+
assertThat(shouldBeFailure.isFailure()).isTrue();
60+
assertThat(authTokenFailure).isSameAs(shouldBeFailure);
61+
});
62+
}
63+
}

cloudplatform/security/src/main/resources/META-INF/services/com.sap.cloud.sdk.cloudplatform.security.AuthTokenFacade

-1
This file was deleted.

cloudplatform/security/src/main/resources/META-INF/services/com.sap.cloud.sdk.cloudplatform.security.secret.SecretStoreFacade

-1
This file was deleted.

cloudplatform/security/src/main/resources/META-INF/services/com.sap.cloud.sdk.cloudplatform.security.user.UserFacade

-1
This file was deleted.

release_notes.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020

2121
### 🐛 Fixed Issues
2222

23-
-
23+
- Fix an issue where the `AuthTokenAccessor` would not recognise JWT tokens passed in via the `dwc-jwt` header.

0 commit comments

Comments
 (0)