Repository: SAP/cloud-security-xsuaa-integration
Pull request #71 (2019-04-26 13:12:44)

Fix allowed audiences
[XsuaaAudienceValidator.allowedAudiences()](https://github.com/SAP/cloud-security-xsuaa-integration/blob/master/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidator.java#L54)
- should not return blanks ("") as audience in the list (this can happen, if the xsuaa.xsappname is "")
- should not return duplicates

Related issue:
#62 

nenaraab: @mwdb 
can you please perform a review?
Thanks :-)

Patch:
diff --git a/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidator.java b/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidator.java
index 9f9dc55b..e347a4a7 100644
--- a/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidator.java
+++ b/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidator.java
@@ -2,16 +2,16 @@ package com.sap.cloud.security.xsuaa.token.authentication;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
+import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration;
+import com.sap.cloud.security.xsuaa.token.Token;
 import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
 import org.springframework.security.oauth2.jwt.Jwt;
 
-import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration;
-import com.sap.cloud.security.xsuaa.token.Token;
-
 /**
  * Validate audience using audience field content. in case this field is empty,
  * the audience is derived from the scope field
@@ -34,7 +34,7 @@ public class XsuaaAudienceValidator implements OAuth2TokenValidator<Jwt> {
 			return OAuth2TokenValidatorResult.success();
 		} else {
 			// case 2: foreign token
-			List<String> allowedAudiences = allowedAudiences(token);
+			List<String> allowedAudiences = getAllowedAudiences(token);
 			if (allowedAudiences.contains(xsuaaServiceConfiguration.getAppId())) {
 				return OAuth2TokenValidatorResult.success();
 			} else {
@@ -51,7 +51,7 @@ public class XsuaaAudienceValidator implements OAuth2TokenValidator<Jwt> {
 	 * @param token
 	 * @return (empty) list of audiences
 	 */
-	private List<String> allowedAudiences(Jwt token) {
+	List<String> getAllowedAudiences(Jwt token) {
 		List<String> allAudiences = new ArrayList<>();
 		List<String> tokenAudiences = token.getAudience();
 
@@ -75,7 +75,7 @@ public class XsuaaAudienceValidator implements OAuth2TokenValidator<Jwt> {
 				}
 			}
 		}
-		return allAudiences;
+		return allAudiences.stream().distinct().filter(value -> !value.isEmpty()).collect(Collectors.toList());
 	}
 
 	private List<String> getScopes(Jwt token) {


Test patch:
diff --git a/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java b/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java
index f77748f3..e62055bf 100644
--- a/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java
+++ b/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java
@@ -198,9 +198,10 @@ public class JwtGenerator {
 		for (String scope : scopes) {
 			if (scope.contains(".")) {
 				String aud = scope.substring(0, scope.indexOf("."));
-				if (!audiences.contains(aud)) {
-					audiences.add(aud);
+				if (aud.isEmpty() || audiences.contains(aud)) {
+					break;
 				}
+				audiences.add(aud);
 			}
 		}
 		return audiences;
diff --git a/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java b/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java
index cbb6ac6a..86ac06c9 100644
--- a/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java
+++ b/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java
@@ -109,7 +109,7 @@ public class JwtGeneratorTest {
 	}
 
 	@Test
-	public void testTokenWithCustomClaims() throws IOException {
+	public void testTokenWithCustomClaims() {
 		Map<String, Object> claims = new HashMap<>();
 		claims.put("myCustomClaim", "myCustomClaimValue");
 		Jwt jwt = jwtGenerator.addCustomClaims(claims).getToken();
@@ -118,9 +118,9 @@ public class JwtGeneratorTest {
 	}
 
 	@Test
-	public void testTokenWithAudienceClaims() throws IOException {
+	public void testTokenWithDerivedAudienceClaim() {
 
-		Jwt jwt = jwtGenerator.addScopes("openid", "app1.scope", "app2.sub.scope", "app2.scope").deriveAudiences(true)
+		Jwt jwt = jwtGenerator.addScopes("openid", "app1.scope", "app2.sub.scope", "app2.scope", ".scopeWithoutAppId").deriveAudiences(true)
 				.getToken();
 
 		assertThat(jwt.getAudience().size(), equalTo(2));
diff --git a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java
index 9d70ebfd..09e7384c 100644
--- a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java
+++ b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java
@@ -1,5 +1,8 @@
 package com.sap.cloud.security.xsuaa.token.authentication;
 
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Date;
@@ -53,9 +56,18 @@ public class XsuaaAudienceValidatorTest {
 
 	@Test
 	public void testSameClientIdWithoutAudience() {
-		OAuth2TokenValidatorResult result2 = new XsuaaAudienceValidator(serviceConfigurationSameClientId)
+		OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationSameClientId)
 				.validate(tokenWithoutAudience);
-		Assert.assertFalse(result2.hasErrors());
+		Assert.assertFalse(result.hasErrors());
+	}
+
+	@Test
+	public void testExtractAudiencesFromTokenScopes() {
+		Jwt token = new JwtGenerator().addScopes("test1!t1.read","test2!t1.read","test2!t1.write", ".scopeWithoutAppId").getToken();
+		List<String> audiences = new XsuaaAudienceValidator(serviceConfigurationSameClientId).getAllowedAudiences(token);
+		Assert.assertThat(audiences.size(), is(2));
+		Assert.assertThat(audiences, hasItem("test1!t1"));
+		Assert.assertThat(audiences, hasItem("test2!t1"));
 	}
 
 	@Test