From d78b8abebfbacd25071aa2d861a47d5ee0354d0f Mon Sep 17 00:00:00 2001 From: Rocky Zhang Date: Mon, 2 Sep 2024 16:16:56 +0800 Subject: [PATCH] fix: issue #557: DwC Auth Token not available (DwC + IAS) (#568) Co-authored-by: Zhang, Rocky Co-authored-by: Matthias Kuhr <52661546+MatKuhr@users.noreply.github.com> --- .../sdk/cloudplatform/DwcHeaderUtils.java | 27 +++++++++++++- .../security/DwcAuthTokenFacadeTest.java | 35 ++++++++++++++++++- release_notes.md | 2 +- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/cloudplatform/connectivity-dwc/src/main/java/com/sap/cloud/sdk/cloudplatform/DwcHeaderUtils.java b/cloudplatform/connectivity-dwc/src/main/java/com/sap/cloud/sdk/cloudplatform/DwcHeaderUtils.java index c5ed33039..e1c63a94b 100644 --- a/cloudplatform/connectivity-dwc/src/main/java/com/sap/cloud/sdk/cloudplatform/DwcHeaderUtils.java +++ b/cloudplatform/connectivity-dwc/src/main/java/com/sap/cloud/sdk/cloudplatform/DwcHeaderUtils.java @@ -41,6 +41,10 @@ public class DwcHeaderUtils * The name of the header that contains the Deploy with Confidence JWT token. */ public static final String DWC_JWT_HEADER = "dwc-jwt"; + /** + * The name of the header that contains the Deploy with Confidence JWT token issued by IAS. + */ + public static final String DWC_IAS_JWT_HEADER = "dwc-ias-jwt"; /** * This method fetches the value of the {@link #DWC_TENANT_HEADER} header or throws an @@ -117,7 +121,21 @@ public static String getDwcPrincipalIdOrThrow() @Nonnull public static String getDwcJwtOrThrow() { - return getNonEmptyDwcHeaderValue(DWC_JWT_HEADER); + final RequestHeaderContainer container = + RequestHeaderAccessor + .tryGetHeaderContainer() + .getOrElseThrow(e -> new DwcHeaderNotFoundException("Unable to get current request headers.", e)); + + if( !container.containsHeader(DWC_JWT_HEADER) && !container.containsHeader(DWC_IAS_JWT_HEADER) ) { + throw new DwcHeaderNotFoundException( + "Unable to find the " + DWC_JWT_HEADER + " or " + DWC_IAS_JWT_HEADER + " in header."); + } + + if( container.containsHeader(DWC_IAS_JWT_HEADER) ) { + return doGetNonEmptyDwcHeaderValue(container, DWC_IAS_JWT_HEADER); + } + + return doGetNonEmptyDwcHeaderValue(container, DWC_JWT_HEADER); } @Nonnull @@ -129,6 +147,13 @@ private static String getNonEmptyDwcHeaderValue( @Nonnull final String key ) .tryGetHeaderContainer() .getOrElseThrow(e -> new DwcHeaderNotFoundException("Unable to read the " + key + " header value.", e)); + return doGetNonEmptyDwcHeaderValue(container, key); + } + + private static + String + doGetNonEmptyDwcHeaderValue( @Nonnull final RequestHeaderContainer container, final String key ) + { return container .getHeaderValues(key) .stream() diff --git a/cloudplatform/connectivity-dwc/src/test/java/com/sap/cloud/sdk/cloudplatform/security/DwcAuthTokenFacadeTest.java b/cloudplatform/connectivity-dwc/src/test/java/com/sap/cloud/sdk/cloudplatform/security/DwcAuthTokenFacadeTest.java index 7bca4f76c..5042cd506 100644 --- a/cloudplatform/connectivity-dwc/src/test/java/com/sap/cloud/sdk/cloudplatform/security/DwcAuthTokenFacadeTest.java +++ b/cloudplatform/connectivity-dwc/src/test/java/com/sap/cloud/sdk/cloudplatform/security/DwcAuthTokenFacadeTest.java @@ -1,5 +1,6 @@ package com.sap.cloud.sdk.cloudplatform.security; +import static com.sap.cloud.sdk.cloudplatform.DwcHeaderUtils.DWC_IAS_JWT_HEADER; import static com.sap.cloud.sdk.cloudplatform.DwcHeaderUtils.DWC_JWT_HEADER; import static org.assertj.core.api.Assertions.assertThat; @@ -28,11 +29,43 @@ void testFacadeIsPickedUpAutomatically() @Test void testSuccessfulAuthTokenRetrieval() + { + this.doTestSuccessfulAuthTokenRetrieval(DWC_JWT_HEADER); + } + + @Test + void testSuccessfulIasAuthTokenRetrieval() + { + this.doTestSuccessfulAuthTokenRetrieval(DWC_IAS_JWT_HEADER); + } + + void doTestSuccessfulAuthTokenRetrieval( String dwcHeaderKey ) { final String token = JWT.create().sign(Algorithm.none()); final AuthToken expectedToken = new AuthToken(JWT.decode(token)); - final Map headers = ImmutableMap.of(DWC_JWT_HEADER, token); + final Map headers = ImmutableMap.of(dwcHeaderKey, token); + + RequestHeaderAccessor.executeWithHeaderContainer(headers, () -> { + final ThreadContext currentContext = ThreadContextAccessor.getCurrentContext(); + final AuthToken currentToken = AuthTokenAccessor.getCurrentToken(); + final Try maybeTokenFromContext = + currentContext.getPropertyValue(AuthTokenThreadContextListener.PROPERTY_AUTH_TOKEN); + + assertThat(currentToken).isEqualTo(expectedToken); + assertThat(maybeTokenFromContext).contains(expectedToken); + }); + } + + @Test + void testIasAuthTokenTakePrecedenceInRetrieval() + { + final String iasToken = JWT.create().sign(Algorithm.none()); + final String xsuaaToken = JWT.create().sign(Algorithm.none()); + + final AuthToken expectedToken = new AuthToken(JWT.decode(iasToken)); + + final Map headers = ImmutableMap.of(DWC_IAS_JWT_HEADER, iasToken, DWC_JWT_HEADER, xsuaaToken); RequestHeaderAccessor.executeWithHeaderContainer(headers, () -> { final ThreadContext currentContext = ThreadContextAccessor.getCurrentContext(); diff --git a/release_notes.md b/release_notes.md index 948a8d2b2..04a978435 100644 --- a/release_notes.md +++ b/release_notes.md @@ -35,5 +35,5 @@ In case of an error a potential response body will now be logged with the error message. ### 🐛 Fixed Issues - +- fix: issue [#557](https://github.com/SAP/cloud-sdk-java/issues/557): DwC Auth Token not available (DwC + IAS) by @jingweiz2017 in #568 - Fix an issue where proxy headers are applied multiple times for OnPremise destinations.