Repository: SAP/cloud-security-xsuaa-integration
Pull request #315 (2020-06-25 14:51:14)

JwtAudienceValidator should also compare client ids
solves NGPBUG-120051


Patch:
diff --git a/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidator.java b/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidator.java
index 12ace393..754f38b8 100644
--- a/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidator.java
+++ b/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidator.java
@@ -2,6 +2,7 @@ package com.sap.cloud.security.token.validation.validators;
 
 import static com.sap.cloud.security.xsuaa.Assertions.assertHasText;
 
+import com.sap.cloud.security.config.Service;
 import com.sap.cloud.security.token.Token;
 import com.sap.cloud.security.token.TokenClaims;
 import com.sap.cloud.security.token.validation.ValidationResult;
@@ -81,6 +82,10 @@ public class JwtAudienceValidator implements Validator<Token> {
 	static Set<String> getAllowedAudiences(Token token) {
 		Set<String> audiences = new LinkedHashSet<>();
 
+		if(Service.XSUAA.equals(token.getService()) && token.hasClaim(TokenClaims.XSUAA.CLIENT_ID)) {
+			audiences.add(token.getClaimAsString(TokenClaims.XSUAA.CLIENT_ID));
+		}
+
 		for (String audience : token.getAudiences()) {
 			if (audience.contains(".")) {
 				// CF UAA derives the audiences from the scopes.
@@ -94,7 +99,7 @@ public class JwtAudienceValidator implements Validator<Token> {
 			}
 		}
 		// extract audience (app-id) from scopes
-		if (audiences.isEmpty()) {
+		if (audiences.isEmpty() && Service.XSUAA.equals(token.getService())) {
 			for (String scope : token.getClaimAsStringList(TokenClaims.XSUAA.SCOPES)) {
 				if (scope.contains(".")) {
 					audiences.add(extractAppId(scope));


Test patch:
diff --git a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidatorTest.java b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidatorTest.java
index 282e1fe1..5e5752d4 100644
--- a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidatorTest.java
+++ b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtAudienceValidatorTest.java
@@ -1,5 +1,6 @@
 package com.sap.cloud.security.token.validation.validators;
 
+import com.sap.cloud.security.config.Service;
 import com.sap.cloud.security.token.Token;
 import com.sap.cloud.security.token.TokenClaims;
 import com.sap.cloud.security.token.validation.ValidationResult;
@@ -24,6 +25,7 @@ public class JwtAudienceValidatorTest {
 		token = Mockito.mock(Token.class);
 		Mockito.when(token.getAudiences()).thenReturn(
 				Sets.newLinkedHashSet("client", "foreignclient", "sb-test4!t1.data"));
+		Mockito.when(token.getService()).thenReturn(Service.XSUAA);
 	}
 
 	@Test
@@ -66,6 +68,19 @@ public class JwtAudienceValidatorTest {
 		assertThat(result.isValid()).isTrue(); // should match
 	}
 
+	@Test
+	public void validate_tokenClientIdMatchesTrustedClientId() {
+		// configures token audience
+		Mockito.when(token.hasClaim(TokenClaims.XSUAA.CLIENT_ID)).thenReturn(true);
+		Mockito.when(token.getClaimAsString(TokenClaims.XSUAA.CLIENT_ID)).thenReturn("sb-myclientid!t1");
+
+		// configures audience validator with client-id from VCAP_SERVICES
+		ValidationResult result = new JwtAudienceValidator("sb-myclientid!t1")
+				.validate(token);
+
+		assertThat(result.isValid()).isTrue(); // should match
+	}
+
 	@Test
 	public void validate_brokerClientIdMatchesCloneAudience() {
 		// configures token audience