Repository: SAP/cloud-security-xsuaa-integration
Pull request #872 (2022-04-12 12:47:47)

Bump reactor-test from 3.4.16 to 3.4.17
Bumps [reactor-test](https://github.com/reactor/reactor-core) from 3.4.16 to 3.4.17.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/reactor/reactor-core/releases">reactor-test's releases</a>.</em></p>
<blockquote>
<h2>v3.4.17</h2>
<p>Reactor-Core <code>3.4.17</code> is part of <strong><code>2020.0.18</code> Release Train (<code>Europium</code> SR18)</strong>.</p>
<!-- raw HTML omitted -->
<h3>:warning: Update considerations and deprecations</h3>
<ul>
<li>Deprecate [Flux|Mono|Synchronous]Sink currentContext by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2974">#2974</a></li>
</ul>
<h3>:lady_beetle: Bug fixes</h3>
<ul>
<li>[agent] Avoid instrumenting methods with unwrappable returnType by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2973">#2973</a></li>
<li>Avoid FluxReplay buffer retaining/leaking with tiny TTL by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2998">#2998</a></li>
<li>Fix subscribers being retained by SinkOneMulticast by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/3002">#3002</a></li>
</ul>
<h3>:book: Documentation, Tests and Build</h3>
<ul>
<li>[test] Fix flaky BoundedElasticTest with better controlled tasks by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2968">#2968</a></li>
<li>[doc] Polish Schedulers javadoc for common/cached instances by <a href="https://github.com/dedeibel"><code>@​dedeibel</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2995">#2995</a></li>
<li>[test] Improve flaky BoundedElasticScheduler toString test by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/3010">#3010</a></li>
</ul>
<h3>:up: Dependency Upgrades</h3>
<ul>
<li>April round of upgrades: Gradle 7.4.2, plugins (download, jmh, spotless, artifactory, gradle enterprise)  by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2992">#2992</a></li>
<li>Update gradle/gradle-build-action to v2.1.5 by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2996">#2996</a></li>
<li>Update ByteBuddy to v1.12.9 by <a href="https://github.com/simonbasle"><code>@​simonbasle</code></a> in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/3008">#3008</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/dedeibel"><code>@​dedeibel</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2995">#2995</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/reactor/reactor-core/commit/8c1e4bef4c7708de5ac0fa32a4414088f4c09622"><code>8c1e4be</code></a> [release] Prepare and release 3.4.17</li>
<li><a href="https://github.com/reactor/reactor-core/commit/0b0ed3338d12d532183834182b0369d3ea428b8f"><code>0b0ed33</code></a> [test] Improve flaky BoundedElasticScheduler toString test (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/3010">#3010</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/2c3de5d44c24414df06c38e45aec0cf7ca9d7df5"><code>2c3de5d</code></a> [doc] Polish Schedulers javadoc for common/cached instances (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2995">#2995</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/1bd2d3eda5cefcaa38baa3be35b1ce89049d8cf7"><code>1bd2d3e</code></a> Update ByteBuddy to v1.12.9 (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/3008">#3008</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/8069f4cfad6de3b615caa6dae1eb62dcf4b81d2e"><code>8069f4c</code></a> Fix subscribers being retained by SinkOneMulticast (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/3002">#3002</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/5297df90628666d12bfea833d17c9963fe50094d"><code>5297df9</code></a> Avoid FluxReplay buffer retaining/leaking with tiny TTL (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2998">#2998</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/67319ff8600c24870b2704947fff9cf66d361b35"><code>67319ff</code></a> Update gradle/gradle-build-action to v2.1.5 (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2996">#2996</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/95f1046a1b3e4697a0cd493c078bbce5e7af2394"><code>95f1046</code></a> Upgrade gradle-build-action to v2.1.5 (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2992">#2992</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/cc6a76eb1d29c3c42d37068d75960066668d6450"><code>cc6a76e</code></a> Update Gradle to v7.4.2 (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2992">#2992</a>)</li>
<li><a href="https://github.com/reactor/reactor-core/commit/29cc97eaa7ee911b38c299a48d502519b6bced47"><code>29cc97e</code></a> Update several test / plugin dependencies in 3.4.x (<a href="https://github-redirect.dependabot.com/reactor/reactor-core/issues/2992">#2992</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/reactor/reactor-core/compare/v3.4.16...v3.4.17">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=io.projectreactor:reactor-test&package-manager=maven&previous-version=3.4.16&new-version=3.4.17)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtSignatureValidator.java b/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtSignatureValidator.java
index 472e538e..a28aafa2 100644
--- a/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtSignatureValidator.java
+++ b/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtSignatureValidator.java
@@ -62,10 +62,13 @@ class JwtSignatureValidator implements Validator<Token> {
 	public ValidationResult validate(Token token) {
 		String jwksUri;
 		String keyId;
+		String zoneIdForTokenKeys = null;
 
-		if (Service.IAS == configuration.getService() && !token.getIssuer().equals("" + configuration.getUrl())
-				&& token.getZoneId() == null) { // lgtm[java/dereferenced-value-may-be-null]
-			return createInvalid("Error occurred during signature validation: OIDC token must provide zone_uuid.");
+		if (Service.IAS == configuration.getService()) {
+			zoneIdForTokenKeys = token.getZoneId();
+			if (!token.getIssuer().equals("" + configuration.getUrl()) && zoneIdForTokenKeys  == null) { // lgtm[java/dereferenced-value-may-be-null]
+				return createInvalid("Error occurred during signature validation: OIDC token must provide zone_uuid.");
+			}
 		}
 		try {
 			jwksUri = getOrRequestJwksUri(token);
@@ -79,7 +82,7 @@ class JwtSignatureValidator implements Validator<Token> {
 					keyId,
 					jwksUri,
 					fallbackPublicKey,
-					token.getZoneId());
+					zoneIdForTokenKeys);
 		} catch (OAuth2ServiceException | IllegalArgumentException e) {
 			return createInvalid("Error occurred during jwks uri determination: {}", e.getMessage());
 		}
@@ -250,7 +253,7 @@ class JwtSignatureValidator implements Validator<Token> {
 					return createValid();
 				}
 				return createInvalid(
-						"Signature of Jwt Token is not valid: the identity provided by the JSON Web Token Key can not be verified.");
+						"Signature of Jwt Token is not valid: the identity provided by the JSON Web Token Key can not be verified (Signature: {}).", tokenHeaderPayloadSignature[2]);
 			} catch (Exception e) {
 				return createInvalid("Error occurred during Json Web Signature Validation: {}.", e.getMessage());
 			}
diff --git a/pom.xml b/pom.xml
index ed872c3e..4493ad74 100644
--- a/pom.xml
+++ b/pom.xml
@@ -63,7 +63,7 @@
 		<spring.security.version>5.6.2</spring.security.version>
 		<spring.security.oauth2.version>2.5.1.RELEASE</spring.security.oauth2.version>
 		<spring.security.jwt.version>1.1.1.RELEASE</spring.security.jwt.version>
-		<reactor.version>3.4.16</reactor.version>
+		<reactor.version>3.4.17</reactor.version>
 		<log4j2.version>2.17.2</log4j2.version>
 		<slf4j.api.version>1.7.36</slf4j.api.version> <!--see also here http://www.slf4j.org/faq.html#changesInVersion18 -->
 		<org.json.version>20220320</org.json.version>
@@ -79,7 +79,7 @@
 		<hamcrest.version>1.3</hamcrest.version>
 		<mockito.version>3.12.4</mockito.version>
 		<assertj.version>3.22.0</assertj.version>
-		<reactor.test.version>3.4.16</reactor.test.version>
+		<reactor.test.version>3.4.17</reactor.test.version>
 		<wiremock.version>2.32.0</wiremock.version>
 		<javax.annotation.version>1.3.2</javax.annotation.version>
 		<spotbugs.annotations.version>4.6.0</spotbugs.annotations.version>


Test patch:
diff --git a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/OAuth2TokenKeyServiceWithCacheTest.java b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/OAuth2TokenKeyServiceWithCacheTest.java
index 9507d0bb..62ffd84f 100644
--- a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/OAuth2TokenKeyServiceWithCacheTest.java
+++ b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/OAuth2TokenKeyServiceWithCacheTest.java
@@ -42,7 +42,7 @@ public class OAuth2TokenKeyServiceWithCacheTest {
 	@Before
 	public void setup() throws IOException {
 		tokenKeyServiceMock = mock(OAuth2TokenKeyService.class);
-		when(tokenKeyServiceMock.retrieveTokenKeys(eq(TOKEN_KEYS_URI), any()))
+		when(tokenKeyServiceMock.retrieveTokenKeys(eq(TOKEN_KEYS_URI), isNotNull()))
 				.thenReturn(IOUtils.resourceToString("/jsonWebTokenKeys.json", StandardCharsets.UTF_8));
 
 		testCacheTicker = new TestCacheTicker();
@@ -84,10 +84,13 @@ public class OAuth2TokenKeyServiceWithCacheTest {
 
 	@Test
 	public void retrieveTokenKeys() throws OAuth2ServiceException, InvalidKeySpecException, NoSuchAlgorithmException {
-		PublicKey key = cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, ZONE_ID);
+		PublicKey key1 = cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, ZONE_ID);
+		PublicKey key2 = cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, "other-zone-id");
 
-		assertThat(String.valueOf(key.getAlgorithm())).isEqualTo("RSA");
+		assertThat(String.valueOf(key1.getAlgorithm())).isEqualTo("RSA");
+		assertThat(String.valueOf(key2.getAlgorithm())).isEqualTo("RSA");
 		verify(tokenKeyServiceMock, times(1)).retrieveTokenKeys(eq(TOKEN_KEYS_URI), eq(ZONE_ID));
+		verify(tokenKeyServiceMock, times(1)).retrieveTokenKeys(eq(TOKEN_KEYS_URI), eq("other-zone-id"));
 	}
 
 	@Test
@@ -122,14 +125,27 @@ public class OAuth2TokenKeyServiceWithCacheTest {
 	@Test
 	public void retrieveTokenKeys_afterCacheWasCleared()
 			throws OAuth2ServiceException, InvalidKeySpecException, NoSuchAlgorithmException {
-		cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, null);
+		cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, ZONE_ID);
 		cut.clearCache();
+		PublicKey cachedKey = cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, ZONE_ID);
+
+		assertThat(cachedKey).isNotNull();
+		verify(tokenKeyServiceMock, times(2)).retrieveTokenKeys(eq(TOKEN_KEYS_URI), eq(ZONE_ID));
+	}
+
+	@Test
+	public void getCachedTokenKeys_noZoneId() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
+		when(tokenKeyServiceMock.retrieveTokenKeys(eq(TOKEN_KEYS_URI), isNull()))
+				.thenReturn(IOUtils.resourceToString("/jsonWebTokenKeys.json", StandardCharsets.UTF_8));
+		PublicKey key = cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, null);
 		PublicKey cachedKey = cut.getPublicKey(JwtSignatureAlgorithm.RS256, "key-id-0", TOKEN_KEYS_URI, null);
 
 		assertThat(cachedKey).isNotNull();
-		verify(tokenKeyServiceMock, times(2)).retrieveTokenKeys(eq(TOKEN_KEYS_URI), eq(null));
+		assertThat(cachedKey).isSameAs(key);
+		verify(tokenKeyServiceMock, times(1)).retrieveTokenKeys(eq(TOKEN_KEYS_URI), isNull());
 	}
 
+
 	@Test
 	public void retrieveTokenKeys_doesRequestKeysAgainAfterCacheExpired()
 			throws OAuth2ServiceException, InvalidKeySpecException, NoSuchAlgorithmException {
diff --git a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/XsuaaJwtSignatureValidatorTest.java b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/XsuaaJwtSignatureValidatorTest.java
index 3a146f08..890d638a 100644
--- a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/XsuaaJwtSignatureValidatorTest.java
+++ b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/XsuaaJwtSignatureValidatorTest.java
@@ -25,8 +25,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.when;
 
 public class XsuaaJwtSignatureValidatorTest {
@@ -59,7 +58,7 @@ public class XsuaaJwtSignatureValidatorTest {
 		tokenKeyServiceMock = Mockito.mock(OAuth2TokenKeyService.class);
 		when(tokenKeyServiceMock
 				.retrieveTokenKeys(eq(URI.create("https://authentication.stagingaws.hanavlab.ondemand.com/token_keys")),
-						any()))
+						isNull()))
 								.thenReturn(IOUtils.resourceToString("/jsonWebTokenKeys.json", UTF_8));
 
 		cut = new JwtSignatureValidator(
@@ -124,7 +123,11 @@ public class XsuaaJwtSignatureValidatorTest {
 		ValidationResult result = cut.validate(xsuaaTokenSignedWithVerificationKey);
 		assertThat(result.isErroneous(), is(true));
 		assertThat(result.getErrorDescription(),
-				containsString("Signature of Jwt Token is not valid"));
+				containsString("Signature of Jwt Token is not valid")
+		);
+		assertThat(result.getErrorDescription(),
+				containsString("(Signature: CetA62rQSNRj93S9mqaHrKJyzONKeEKcEJ9O5wObRD_")
+		);
 	}
 
 }
diff --git a/token-client/src/test/java/com/sap/cloud/security/xsuaa/client/DefaultOAuth2TokenKeyServiceTest.java b/token-client/src/test/java/com/sap/cloud/security/xsuaa/client/DefaultOAuth2TokenKeyServiceTest.java
index dbd8bb18..a0efae13 100644
--- a/token-client/src/test/java/com/sap/cloud/security/xsuaa/client/DefaultOAuth2TokenKeyServiceTest.java
+++ b/token-client/src/test/java/com/sap/cloud/security/xsuaa/client/DefaultOAuth2TokenKeyServiceTest.java
@@ -54,7 +54,7 @@ public class DefaultOAuth2TokenKeyServiceTest {
 	}
 
 	@Test
-	public void retrieveTokenKeys_responseNotOk_throwsException() throws IOException {
+	public void retrieveTokenKeysForZone_responseNotOk_throwsException() throws IOException {
 		String errorDescription = "Something went wrong";
 		CloseableHttpResponse response = HttpClientTestFactory
 				.createHttpResponse(errorDescription, HttpStatus.SC_BAD_REQUEST);
@@ -68,6 +68,20 @@ public class DefaultOAuth2TokenKeyServiceTest {
 				.hasMessageContaining("Headers [x-zone_uuid=92768714-4c2e-4b79-bc1b-009a4127ee3c]");
 	}
 
+	@Test
+	public void retrieveTokenKeys_responseNotOk_throwsException() throws IOException {
+		String errorDescription = "Something went wrong";
+		CloseableHttpResponse response = HttpClientTestFactory
+				.createHttpResponse(errorDescription, HttpStatus.SC_BAD_REQUEST);
+		when(httpClient.execute(any())).thenReturn(response);
+
+		assertThatThrownBy(() -> cut.retrieveTokenKeys(TOKEN_KEYS_ENDPOINT_URI, null))
+				.isInstanceOf(OAuth2ServiceException.class)
+				.hasMessageContaining(errorDescription)
+				.hasMessageContaining("'Something went wrong'")
+				.hasMessageContaining("Error retrieving token keys");
+	}
+
 	@Test
 	public void retrieveTokenKeys_tokenEndpointUriIsNull_throwsException() {
 		assertThatThrownBy(() -> cut.retrieveTokenKeys(null, ZONE_UUID))