Repository: SAP/cloud-security-xsuaa-integration
Pull request #814 (2022-02-04 10:46:32)

bump version to 2.11.13


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f7b4556..69d647ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,7 +36,7 @@ All notable changes to this project will be documented in this file.
         <dependency>
             <groupId>com.sap.cloud.security</groupId>
             <artifactId>java-bom</artifactId>
-            <version>2.11.9</version>
+            <version>...</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
diff --git a/api/README.md b/api/README.md
index dc2e3ed7..59e35ee6 100644
--- a/api/README.md
+++ b/api/README.md
@@ -5,6 +5,6 @@
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>api</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 ```
diff --git a/api/pom.xml b/api/pom.xml
index 83bcf057..3361c0a4 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -11,7 +11,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<packaging>jar</packaging>
diff --git a/bom/pom.xml b/bom/pom.xml
index 3b56cbd8..8c4a734c 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -8,7 +8,7 @@
 
     <groupId>com.sap.cloud.security</groupId>
     <artifactId>java-bom</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
     <packaging>pom</packaging>
     <name>java-bom</name>
 
diff --git a/env/pom.xml b/env/pom.xml
index 533c7287..7e72d7e2 100644
--- a/env/pom.xml
+++ b/env/pom.xml
@@ -9,7 +9,7 @@
     <parent>
         <groupId>com.sap.cloud.security.xsuaa</groupId>
         <artifactId>parent</artifactId>
-        <version>2.11.12</version>
+        <version>2.11.13</version>
     </parent>
 
     <groupId>com.sap.cloud.security</groupId>
diff --git a/java-api/README.md b/java-api/README.md
index e18966ca..a2cda361 100644
--- a/java-api/README.md
+++ b/java-api/README.md
@@ -5,6 +5,6 @@
 <dependency>
     <groupId>com.sap.cloud.security</groupId>
     <artifactId>java-api</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 ```
diff --git a/java-api/pom.xml b/java-api/pom.xml
index 168ae9fb..004dc01b 100644
--- a/java-api/pom.xml
+++ b/java-api/pom.xml
@@ -9,7 +9,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<groupId>com.sap.cloud.security</groupId>
diff --git a/java-security-it/pom.xml b/java-security-it/pom.xml
index 024c3951..f6d44bc6 100644
--- a/java-security-it/pom.xml
+++ b/java-security-it/pom.xml
@@ -9,7 +9,7 @@
     <parent>
         <artifactId>parent</artifactId>
         <groupId>com.sap.cloud.security.xsuaa</groupId>
-        <version>2.11.12</version>
+        <version>2.11.13</version>
     </parent>
 
     <artifactId>java-security-it</artifactId>
diff --git a/java-security/Migration_SpringSecurityProjects.md b/java-security/Migration_SpringSecurityProjects.md
index dc85b2b8..f24caa90 100644
--- a/java-security/Migration_SpringSecurityProjects.md
+++ b/java-security/Migration_SpringSecurityProjects.md
@@ -37,19 +37,19 @@ First make sure you have the following dependencies defined in your pom.xml:
 <dependency>
   <groupId>com.sap.cloud.security.xsuaa</groupId>
   <artifactId>api</artifactId>
-  <version>2.11.12</version>
+  <version>2.11.13</version>
 </dependency>
 <dependency>
   <groupId>com.sap.cloud.security</groupId>
   <artifactId>java-security</artifactId>
-  <version>2.11.12</version>
+  <version>2.11.13</version>
 </dependency>
 
 <!-- new java-security dependencies for unit tests -->
 <dependency>
   <groupId>com.sap.cloud.security</groupId>
   <artifactId>java-security-test</artifactId>
-  <version>2.11.12</version>
+  <version>2.11.13</version>
   <scope>test</scope>
 </dependency>
 ```
diff --git a/java-security/README.md b/java-security/README.md
index ca532a4a..cf2a0901 100644
--- a/java-security/README.md
+++ b/java-security/README.md
@@ -47,7 +47,7 @@ In case of XSUAA does the JWT provide a valid `jku` token header parameter that
 <dependency>
     <groupId>com.sap.cloud.security</groupId>
     <artifactId>java-security</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 <dependency>
     <groupId>org.apache.httpcomponents</groupId>
diff --git a/java-security/pom.xml b/java-security/pom.xml
index ba0d04a5..412b905e 100644
--- a/java-security/pom.xml
+++ b/java-security/pom.xml
@@ -9,7 +9,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<groupId>com.sap.cloud.security</groupId>
diff --git a/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidator.java b/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidator.java
index e59ebf10..2bb39ea5 100644
--- a/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidator.java
+++ b/java-security/src/main/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidator.java
@@ -9,6 +9,7 @@ import com.sap.cloud.security.token.validation.ValidationResult;
 import com.sap.cloud.security.token.validation.ValidationResults;
 import com.sap.cloud.security.token.validation.Validator;
 import com.sap.cloud.security.x509.Certificate;
+import com.sap.cloud.security.xsuaa.Assertions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -29,10 +30,10 @@ import javax.annotation.Nullable;
 public class JwtX5tValidator implements Validator<Token> {
 
 	private static final Logger LOGGER = LoggerFactory.getLogger(JwtX5tValidator.class);
-	private final OAuth2ServiceConfiguration config;
+	static final String VALIDATION_FAILED = "Certificate thumbprint validation failed";
 
 	public JwtX5tValidator(OAuth2ServiceConfiguration config) {
-		this.config = config;
+		Assertions.assertNotNull(config, "Service configuration must not be null");
 	}
 
 	/**
@@ -50,29 +51,23 @@ public class JwtX5tValidator implements Validator<Token> {
 	 */
 	@Override
 	public ValidationResult validate(Token token) {
+		if (token == null) {
+			return ValidationResults.createInvalid("No token passed to validate certificate thumbprint");
+		}
 		String tokenX5t = extractCnfThumbprintFromToken(token);
 		LOGGER.debug("Token 'cnf' thumbprint: {}", tokenX5t);
-		if (tokenX5t != null) {
-			Certificate clientCertificate = SecurityContext.getClientCertificate();
-			if (clientCertificate == null) {
-				LOGGER.error("Client certificate missing from SecurityContext");
-				return ValidationResults.createInvalid("Certificate validation failed");
-			}
-			String clientCertificateX5t = clientCertificate.getThumbprint();
-			if (clientCertificateX5t.equals(tokenX5t)) {
-				if (token.getAudiences().size() == 1 && token.getAudiences().contains(config.getClientId())) {
-					return ValidationResults.createValid();
-				}
-				LOGGER.error("Audience validation failed -> \"aud\": {} != \"clientid\": \"{}\"", token.getAudiences(),
-						config.getClientId());
-			} else {
-				LOGGER.error(
-						"Thumbprint validation failed -> x5t from token: \"{}\" != thumbprint from client certificate: \"{}\"",
-						tokenX5t,
-						clientCertificateX5t);
-			}
+		if (tokenX5t == null) {
+			return ValidationResults.createInvalid("Token doesn't contain certificate thumbprint confirmation method");
+		}
+		Certificate clientCertificate = SecurityContext.getClientCertificate();
+		if (clientCertificate == null) {
+			return ValidationResults.createInvalid("Client certificate missing from SecurityContext");
+		}
+		String clientCertificateX5t = clientCertificate.getThumbprint();
+		if (clientCertificateX5t.equals(tokenX5t)) {
+			return ValidationResults.createValid();
 		}
-		return ValidationResults.createInvalid("Certificate validation failed");
+		return ValidationResults.createInvalid(VALIDATION_FAILED);
 	}
 
 	/**
diff --git a/pom.xml b/pom.xml
index a8c44e9d..0a9f0024 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
 
 	<groupId>com.sap.cloud.security.xsuaa</groupId>
 	<artifactId>parent</artifactId>
-	<version>2.11.12</version>
+	<version>2.11.13</version>
 	<packaging>pom</packaging>
 
 	<name>parent</name>
diff --git a/samples/java-security-usage-ias/pom.xml b/samples/java-security-usage-ias/pom.xml
index 514cf5bc..87930d9a 100755
--- a/samples/java-security-usage-ias/pom.xml
+++ b/samples/java-security-usage-ias/pom.xml
@@ -6,7 +6,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.sap.cloud.security.xssec.samples</groupId>
     <artifactId>java-security-usage-ias</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
     <packaging>war</packaging>
 
     <!--profiles>
@@ -27,7 +27,7 @@
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <sap.cloud.security.version>2.11.12</sap.cloud.security.version>
+        <sap.cloud.security.version>2.11.13</sap.cloud.security.version>
         <slf4j.api.version>1.7.30</slf4j.api.version>
         <apache.httpclient.version>4.5.13</apache.httpclient.version>
         <javax.servlet.api.version>4.0.1</javax.servlet.api.version>
diff --git a/samples/java-security-usage/pom.xml b/samples/java-security-usage/pom.xml
index 5b15cf92..5f2830ba 100755
--- a/samples/java-security-usage/pom.xml
+++ b/samples/java-security-usage/pom.xml
@@ -6,7 +6,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.sap.cloud.security.xssec.samples</groupId>
     <artifactId>java-security-usage</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
     <packaging>war</packaging>
 
     <!--profiles>
@@ -27,7 +27,7 @@
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <sap.cloud.security.version>2.11.12</sap.cloud.security.version>
+        <sap.cloud.security.version>2.11.13</sap.cloud.security.version>
         <slf4j.api.version>1.7.30</slf4j.api.version>
         <apache.httpclient.version>4.5.13</apache.httpclient.version>
         <javax.servlet.api.version>4.0.1</javax.servlet.api.version>
diff --git a/samples/java-tokenclient-usage/pom.xml b/samples/java-tokenclient-usage/pom.xml
index b82fd3b6..6517dd93 100755
--- a/samples/java-tokenclient-usage/pom.xml
+++ b/samples/java-tokenclient-usage/pom.xml
@@ -6,13 +6,13 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.sap.cloud.security.xssec.samples</groupId>
     <artifactId>java-tokenclient-usage</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
     <packaging>war</packaging>
 
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <sap.cloud.security.version>2.11.12</sap.cloud.security.version>
+        <sap.cloud.security.version>2.11.13</sap.cloud.security.version>
         <apache.httpclient.version>4.5.13</apache.httpclient.version>
         <javax.servlet.api.version>4.0.1</javax.servlet.api.version>
         <slf4j.api.version>1.7.30</slf4j.api.version>
diff --git a/samples/sap-java-buildpack-api-usage/pom.xml b/samples/sap-java-buildpack-api-usage/pom.xml
index b780c0c2..c98cde12 100755
--- a/samples/sap-java-buildpack-api-usage/pom.xml
+++ b/samples/sap-java-buildpack-api-usage/pom.xml
@@ -6,7 +6,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>com.sap.cloud.security.xssec.samples</groupId>
 	<artifactId>sap-java-buildpack-api-usage</artifactId>
-	<version>2.11.12</version>
+	<version>2.11.13</version>
 	<packaging>war</packaging>
 
 	<properties>
diff --git a/samples/spring-security-basic-auth/pom.xml b/samples/spring-security-basic-auth/pom.xml
index 71b8552b..7cc5c10e 100644
--- a/samples/spring-security-basic-auth/pom.xml
+++ b/samples/spring-security-basic-auth/pom.xml
@@ -13,14 +13,14 @@
 	</parent>
 
 	<artifactId>spring-security-basic-auth</artifactId>
-	<version>2.11.12</version>
+	<version>2.11.13</version>
 	<name>spring-security-basic-auth</name>
 
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 		<java.version>1.8</java.version>
-		<sap.cloud.security.version>2.11.12</sap.cloud.security.version>
+		<sap.cloud.security.version>2.11.13</sap.cloud.security.version>
 		<apache.httpclient.version>4.5.13</apache.httpclient.version>
 	</properties>
 
diff --git a/samples/spring-security-hybrid-usage/pom.xml b/samples/spring-security-hybrid-usage/pom.xml
index 973eb534..3d924516 100644
--- a/samples/spring-security-hybrid-usage/pom.xml
+++ b/samples/spring-security-hybrid-usage/pom.xml
@@ -16,7 +16,7 @@
 
 	<groupId>com.sap.cloud.security.samples</groupId>
 	<artifactId>spring-security-hybrid-usage</artifactId>
-	<version>2.11.12</version>
+	<version>2.11.13</version>
 
 	<properties>
 		<!-- 
@@ -28,7 +28,7 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 		<java.version>1.8</java.version>
-		<sap.cloud.security.version>2.11.12</sap.cloud.security.version>
+		<sap.cloud.security.version>2.11.13</sap.cloud.security.version>
 		<apache.httpclient.version>4.5.13</apache.httpclient.version>
 	</properties>
 
diff --git a/samples/spring-security-xsuaa-usage/pom.xml b/samples/spring-security-xsuaa-usage/pom.xml
index d9181f33..44614f7b 100644
--- a/samples/spring-security-xsuaa-usage/pom.xml
+++ b/samples/spring-security-xsuaa-usage/pom.xml
@@ -16,7 +16,7 @@
 
 	<groupId>com.sap.cloud.security.samples</groupId>
 	<artifactId>spring-security-xsuaa-usage</artifactId>
-	<version>2.11.12</version>
+	<version>2.11.13</version>
 	<name>spring-security-xsuaa-usage</name>
 
 	<properties>
@@ -29,7 +29,7 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 		<java.version>1.8</java.version>
-		<sap.cloud.security.version>2.11.12</sap.cloud.security.version>
+		<sap.cloud.security.version>2.11.13</sap.cloud.security.version>
 		<apache.httpclient.version>4.5.13</apache.httpclient.version>
 	</properties>
 
diff --git a/samples/spring-webflux-security-xsuaa-usage/pom.xml b/samples/spring-webflux-security-xsuaa-usage/pom.xml
index e66933c3..c28a5b5b 100644
--- a/samples/spring-webflux-security-xsuaa-usage/pom.xml
+++ b/samples/spring-webflux-security-xsuaa-usage/pom.xml
@@ -14,12 +14,12 @@
 
     <groupId>com.sap.cloud.security.samples</groupId>
     <artifactId>spring-webflux-security-xsuaa-usage</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
     <name>spring-webflux-security-xsuaa-usage</name>
 
     <properties>
         <java.version>1.8</java.version>
-        <sap.cloud.security.version>2.11.12</sap.cloud.security.version>
+        <sap.cloud.security.version>2.11.13</sap.cloud.security.version>
     </properties>
 
     <dependencies>
diff --git a/spring-security-starter/pom.xml b/spring-security-starter/pom.xml
index 030d2138..9453934a 100644
--- a/spring-security-starter/pom.xml
+++ b/spring-security-starter/pom.xml
@@ -16,7 +16,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<groupId>com.sap.cloud.security</groupId>
diff --git a/spring-security/README.md b/spring-security/README.md
index 93c36c58..d9875f99 100644
--- a/spring-security/README.md
+++ b/spring-security/README.md
@@ -45,7 +45,7 @@ These (spring) dependencies needs to be provided:
 <dependency>
     <groupId>com.sap.cloud.security</groupId>
     <artifactId>resourceserver-security-spring-boot-starter</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 <dependency>
     <groupId>org.apache.httpcomponents</groupId>
diff --git a/spring-security/pom.xml b/spring-security/pom.xml
index 10bf3e03..1728b4f1 100644
--- a/spring-security/pom.xml
+++ b/spring-security/pom.xml
@@ -9,13 +9,13 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<groupId>com.sap.cloud.security</groupId>
 	<artifactId>spring-security</artifactId>
 	<packaging>jar</packaging>
-	<version>2.11.12</version>
+	<version>2.11.13</version>
 
 	<dependencies>
 		<dependency>
diff --git a/spring-security/src/main/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfiguration.java b/spring-security/src/main/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfiguration.java
index 8f7318e9..aac753fd 100644
--- a/spring-security/src/main/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfiguration.java
+++ b/spring-security/src/main/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfiguration.java
@@ -59,7 +59,7 @@ public class XsuaaTokenFlowAutoConfiguration {
 	}
 
 	@Bean
-	@Conditional({ PropertyConditions.class })
+	@Conditional(PropertyConditions.class)
 	public XsuaaTokenFlows xsuaaTokenFlows(RestOperations xsuaaRestOperations) {
 		logger.debug("auto-configures XsuaaTokenFlows using {} based restOperations",
 				xsuaaConfig.getClientIdentity().isCertificateBased() ? "certificate" : "client secret");
@@ -76,7 +76,7 @@ public class XsuaaTokenFlowAutoConfiguration {
 	 * @return the {@link RestOperations} instance.
 	 */
 	@Bean
-	@Conditional({ OnNotX509CredentialTypeCondition.class })
+	@Conditional({ OnSecretCredentialTypeCondition.class, NoClientCertificateCondition.class })
 	@ConditionalOnMissingBean
 	public RestOperations restOperations() {
 		logger.warn("In productive environment provide a well configured client secret based RestOperations bean");
@@ -90,7 +90,6 @@ public class XsuaaTokenFlowAutoConfiguration {
 	 * @return the {@link RestOperations} instance.
 	 */
 	@Bean
-	@ConditionalOnProperty(prefix = "sap.security.services.xsuaa", name = "credential-type", havingValue = "x509")
 	@ConditionalOnClass(name = "org.apache.http.impl.client.CloseableHttpClient")
 	@ConditionalOnMissingBean
 	public RestOperations mtlsRestOperations(XsuaaServiceConfiguration xsuaaConfig) {
@@ -98,7 +97,7 @@ public class XsuaaTokenFlowAutoConfiguration {
 		return SpringHttpClient.getInstance().create(xsuaaConfig.getClientIdentity());
 	}
 
-	private static class OnNotX509CredentialTypeCondition implements Condition {
+	private static class OnSecretCredentialTypeCondition implements Condition {
 		@Override
 		public boolean matches(ConditionContext context, @Nonnull AnnotatedTypeMetadata metadata) {
 			CredentialType credentialType = CredentialType
@@ -108,17 +107,25 @@ public class XsuaaTokenFlowAutoConfiguration {
 		}
 	}
 
+	private static class NoClientCertificateCondition implements Condition {
+		@Override
+		public boolean matches(ConditionContext context, @Nonnull AnnotatedTypeMetadata metadata) {
+			return context.getEnvironment().getProperty("sap.security.services.xsuaa.certificate") == null &&
+					context.getEnvironment().getProperty("sap.security.services.xsuaa[0].certificate") == null;
+		}
+	}
+
 	private static class PropertyConditions extends AnyNestedCondition {
 
 		public PropertyConditions() {
 			super(ConfigurationPhase.REGISTER_BEAN);
 		}
 
-		@ConditionalOnProperty(prefix = "sap.security.services", name = "xsuaa[0].clientsecret")
+		@ConditionalOnProperty(prefix = "sap.security.services", name = "xsuaa[0].clientid")
 		static class MultipleBindingsCondition {
 		}
 
-		@ConditionalOnProperty(prefix = "sap.security.services", name = "xsuaa.clientsecret")
+		@ConditionalOnProperty(prefix = "sap.security.services", name = "xsuaa.clientid")
 		static class SingleBindingCondition {
 		}
 	}
diff --git a/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoder.java b/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoder.java
index 3cbcb53a..630b0689 100644
--- a/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoder.java
+++ b/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoder.java
@@ -15,6 +15,8 @@ import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
 import org.springframework.util.Assert;
 
+import javax.annotation.Nullable;
+
 /**
  * Internal class that decodes and validates the provided encoded token using
  * {@code java-security} client library.<br>
@@ -39,7 +41,8 @@ public class HybridJwtDecoder implements JwtDecoder {
 	 *            set of validators that should be used to validate an ias oidc
 	 *            token.
 	 */
-	public HybridJwtDecoder(CombiningValidator<Token> xsuaaValidator, CombiningValidator<Token> iasValidator) {
+	public HybridJwtDecoder(CombiningValidator<Token> xsuaaValidator,
+			@Nullable CombiningValidator<Token> iasValidator) {
 		xsuaaTokenValidators = xsuaaValidator;
 		iasTokenValidators = iasValidator;
 	}
@@ -58,18 +61,21 @@ public class HybridJwtDecoder implements JwtDecoder {
 		ValidationResult validationResult;
 		switch (token.getService()) {
 		case IAS:
+			if (iasTokenValidators == null) {
+				throw new BadJwtException("Tokens issued by IAS service aren't accepted");
+			}
 			validationResult = iasTokenValidators.validate(token);
 			break;
 		case XSUAA:
 			validationResult = xsuaaTokenValidators.validate(token);
 			break;
 		default:
-			throw new BadJwtException("The token of service " + token.getService() + " is not supported.");
+			throw new BadJwtException("Tokens issued by " + token.getService() + " service aren't supported.");
 		}
 		if (validationResult.isErroneous()) {
 			throw new BadJwtException("The token is invalid: " + validationResult.getErrorDescription());
 		}
-		logger.debug("The token of service {} was successfully validated.", token.getService());
+		logger.debug("Token issued by {} service was successfully validated.", token.getService());
 		return jwt;
 	}
 
diff --git a/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilder.java b/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilder.java
index 16cd386d..d3ff61a4 100644
--- a/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilder.java
+++ b/spring-security/src/main/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilder.java
@@ -117,28 +117,35 @@ public class JwtDecoderBuilder {
 	 * @return JwtDecoder
 	 */
 	public JwtDecoder build() {
-		JwtValidatorBuilder iasValidatorBuilder = JwtValidatorBuilder.getInstance(iasConfiguration)
-				.withCacheConfiguration(tokenKeyCacheConfiguration)
-				.withHttpClient(httpClient);
-		for (ValidationListener listener : validationListeners) {
-			iasValidatorBuilder.withValidatorListener(listener);
+		JwtValidatorBuilder iasValidatorBuilder = null;
+		if (iasConfiguration != null && !iasConfiguration.getProperties().isEmpty()) {
+			iasValidatorBuilder = initializeBuilder(iasConfiguration);
 		}
 		if (xsuaaConfigurations != null && !xsuaaConfigurations.isEmpty()) {
 			int index = 0;
-			JwtValidatorBuilder xsuaaValidatorBuilder = JwtValidatorBuilder.getInstance(xsuaaConfigurations.get(index))
-					.withCacheConfiguration(tokenKeyCacheConfiguration)
-					.withHttpClient(httpClient);
+			JwtValidatorBuilder xsuaaValidatorBuilder = initializeBuilder(xsuaaConfigurations.get(index));
 			for (OAuth2ServiceConfiguration xsuaaConfig : xsuaaConfigurations) {
 				if (index++ != 0) {
 					xsuaaValidatorBuilder.configureAnotherServiceInstance(xsuaaConfig);
 				}
 			}
-			for (ValidationListener listener : validationListeners) {
-				xsuaaValidatorBuilder.withValidatorListener(listener);
-			}
 			return new HybridJwtDecoder(xsuaaValidatorBuilder.build(),
-					iasValidatorBuilder.build());
+					iasValidatorBuilder != null ? iasValidatorBuilder.build() : null);
+		}
+		if (iasValidatorBuilder == null) {
+			throw new IllegalStateException("There is no xsuaa and no identity service config.");
+		}
+		return new IasJwtDecoder(iasValidatorBuilder.build()); // lgtm [java/dereferenced-value-may-be-null] - line 136
+	}
+
+
+	private JwtValidatorBuilder initializeBuilder(OAuth2ServiceConfiguration config) {
+		JwtValidatorBuilder builder = JwtValidatorBuilder.getInstance(config)
+				.withCacheConfiguration(tokenKeyCacheConfiguration)
+				.withHttpClient(httpClient);
+		for (ValidationListener listener : validationListeners) {
+			builder.withValidatorListener(listener);
 		}
-		return new IasJwtDecoder(iasValidatorBuilder.build());
+		return builder;
 	}
 }
diff --git a/spring-xsuaa-it/pom.xml b/spring-xsuaa-it/pom.xml
index c44e3afb..c8529fd4 100644
--- a/spring-xsuaa-it/pom.xml
+++ b/spring-xsuaa-it/pom.xml
@@ -8,7 +8,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<artifactId>spring-xsuaa-it</artifactId>
diff --git a/spring-xsuaa-mock/README.md b/spring-xsuaa-mock/README.md
index 1c23133a..163390cf 100644
--- a/spring-xsuaa-mock/README.md
+++ b/spring-xsuaa-mock/README.md
@@ -21,7 +21,7 @@ The default implementation offers already valid *token_keys* for JWT tokens, tha
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>spring-xsuaa-mock</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 <dependency> <!-- new with version 1.5.0 - provided with org.springframework.boot:spring-boot-starter:jar -->
     <groupId>org.springframework.boot</groupId>
diff --git a/spring-xsuaa-mock/pom.xml b/spring-xsuaa-mock/pom.xml
index 8e087177..d5e1f4a0 100644
--- a/spring-xsuaa-mock/pom.xml
+++ b/spring-xsuaa-mock/pom.xml
@@ -9,7 +9,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<artifactId>spring-xsuaa-mock</artifactId>
diff --git a/spring-xsuaa-starter/pom.xml b/spring-xsuaa-starter/pom.xml
index 0aa4730f..63010b98 100644
--- a/spring-xsuaa-starter/pom.xml
+++ b/spring-xsuaa-starter/pom.xml
@@ -16,7 +16,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<artifactId>xsuaa-spring-boot-starter</artifactId>
diff --git a/spring-xsuaa/README.md b/spring-xsuaa/README.md
index 4547418c..b52ab201 100644
--- a/spring-xsuaa/README.md
+++ b/spring-xsuaa/README.md
@@ -35,7 +35,7 @@ These (spring) dependencies needs to be provided:
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>spring-xsuaa</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 <dependency> <!-- new with version 1.5.0 -->
     <groupId>org.apache.logging.log4j</groupId>
@@ -49,7 +49,7 @@ These (spring) dependencies needs to be provided:
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>xsuaa-spring-boot-starter</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 ```
 
diff --git a/spring-xsuaa/pom.xml b/spring-xsuaa/pom.xml
index 3565aad8..eeb5f09c 100644
--- a/spring-xsuaa/pom.xml
+++ b/spring-xsuaa/pom.xml
@@ -9,7 +9,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<artifactId>spring-xsuaa</artifactId>
diff --git a/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefault.java b/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefault.java
index 111eadfa..69df32b0 100644
--- a/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefault.java
+++ b/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefault.java
@@ -5,18 +5,18 @@
  */
 package com.sap.cloud.security.xsuaa;
 
-import com.sap.cloud.security.config.ClientCertificate;
-import com.sap.cloud.security.config.ClientCredentials;
-import com.sap.cloud.security.config.ClientIdentity;
-import com.sap.cloud.security.config.CredentialType;
+import com.sap.cloud.security.config.*;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 
 import java.net.URI;
+import java.util.Objects;
 
 @Configuration
 public class XsuaaServiceConfigurationDefault implements XsuaaServiceConfiguration {
 
+	static final String VCAP_SERVICES_CREDENTIALS = "xsuaa credentials from VCAP_SERVICES/secret must not be null";
+
 	@Value("${xsuaa.clientid:}")
 	private String clientId;
 
@@ -101,4 +101,31 @@ public class XsuaaServiceConfigurationDefault implements XsuaaServiceConfigurati
 		return identity;
 	}
 
+	/**
+	 * This only supports read from VCAP_SERVICES in cf environment or read from
+	 * secrets in kubernetes environment.
+	 * 
+	 * @param name
+	 *            of the credential property
+	 * @return the property value or null if not found
+	 */
+	@Override
+	public String getProperty(String name) {
+		return Objects.requireNonNull(Environments.getCurrent().getXsuaaConfiguration(), VCAP_SERVICES_CREDENTIALS)
+				.getProperty(name);
+	}
+
+	/**
+	 * This only supports VCAP_SERVICES in cf environment or read from secrets in
+	 * kubernetes environment.
+	 * 
+	 * @param name
+	 *            of the credential property
+	 * @return false if property doesn't exist
+	 */
+	@Override
+	public boolean hasProperty(String name) {
+		return Objects.requireNonNull(Environments.getCurrent().getXsuaaConfiguration(), VCAP_SERVICES_CREDENTIALS)
+				.hasProperty(name);
+	}
 }
diff --git a/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration.java b/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration.java
index 0eced4a5..b4fd7e80 100644
--- a/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration.java
+++ b/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration.java
@@ -81,7 +81,7 @@ public class XsuaaAutoConfiguration {
 	 * @return the {@link RestOperations} instance.
 	 */
 	@Bean
-	@Conditional({ OnNotX509CredentialTypeCondition.class })
+	@Conditional({ OnSecretCredentialTypeCondition.class, NoClientCertificateCondition.class })
 	@ConditionalOnMissingBean
 	@ConditionalOnBean(XsuaaServiceConfiguration.class)
 	public RestOperations xsuaaRestOperations() {
@@ -96,7 +96,6 @@ public class XsuaaAutoConfiguration {
 	 * @return the {@link RestOperations} instance.
 	 */
 	@Bean
-	@ConditionalOnProperty(prefix = "xsuaa", name = "credential-type", havingValue = "x509")
 	@ConditionalOnMissingBean
 	@ConditionalOnClass(name = "org.apache.http.impl.client.CloseableHttpClient")
 	@ConditionalOnBean(XsuaaServiceConfiguration.class)
@@ -105,7 +104,7 @@ public class XsuaaAutoConfiguration {
 		return SpringHttpClient.getInstance().create(xsuaaServiceConfiguration.getClientIdentity());
 	}
 
-	private static class OnNotX509CredentialTypeCondition implements Condition {
+	private static class OnSecretCredentialTypeCondition implements Condition {
 		@Override
 		public boolean matches(ConditionContext context, @Nonnull AnnotatedTypeMetadata metadata) {
 			CredentialType credentialType = CredentialType
@@ -115,4 +114,12 @@ public class XsuaaAutoConfiguration {
 		}
 	}
 
+	private static class NoClientCertificateCondition implements Condition {
+		@Override
+		public boolean matches(ConditionContext context, @Nonnull AnnotatedTypeMetadata metadata) {
+			return context.getEnvironment().getProperty("xsuaa.certificate") == null &&
+					context.getEnvironment().getProperty("xsuaa.key") == null;
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/token-client/README.md b/token-client/README.md
index c0964af8..977d11cd 100644
--- a/token-client/README.md
+++ b/token-client/README.md
@@ -23,7 +23,7 @@ The Resource owner password credentials (i.e., username and password) can be use
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>token-client</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 <dependency>
   <groupId>org.apache.httpcomponents</groupId>
@@ -81,7 +81,7 @@ tokenService.clearCache();
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>token-client</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 <dependency>
     <groupId>org.springframework</groupId>
@@ -130,7 +130,7 @@ In context of a Spring Boot application you may like to leverage auto-configurat
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>xsuaa-spring-boot-starter</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
 </dependency>
 <dependency> <!-- required when using Spring Web `RestTemplate` with X.509 authentication method-->
   <groupId>org.apache.httpcomponents</groupId>
diff --git a/token-client/pom.xml b/token-client/pom.xml
index 9c381c6f..bbacae88 100644
--- a/token-client/pom.xml
+++ b/token-client/pom.xml
@@ -9,7 +9,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<artifactId>token-client</artifactId>
diff --git a/token-client/src/main/java/com/sap/cloud/security/xsuaa/Assertions.java b/token-client/src/main/java/com/sap/cloud/security/xsuaa/Assertions.java
index 6dd27222..77ffa279 100644
--- a/token-client/src/main/java/com/sap/cloud/security/xsuaa/Assertions.java
+++ b/token-client/src/main/java/com/sap/cloud/security/xsuaa/Assertions.java
@@ -24,7 +24,7 @@ public class Assertions {
 		}
 	}
 
-	public static void assertNotEmpty(List<String> list, String message) {
+	public static void assertNotEmpty(List<?> list, String message) {
 		if (list == null || list.isEmpty()) {
 			throw new IllegalArgumentException(message);
 		}


Test patch:
diff --git a/java-security-test/README.md b/java-security-test/README.md
index 915095b9..872cbfbc 100644
--- a/java-security-test/README.md
+++ b/java-security-test/README.md
@@ -22,7 +22,7 @@ It includes for example a `JwtGenerator` that generates JSON Web Tokens (JWT) th
 <dependency>
     <groupId>com.sap.cloud.security</groupId>
     <artifactId>java-security-test</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
     <scope>test</scope>
 </dependency>
 ```
diff --git a/java-security-test/pom.xml b/java-security-test/pom.xml
index 969136e8..ce8c9aed 100644
--- a/java-security-test/pom.xml
+++ b/java-security-test/pom.xml
@@ -9,7 +9,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<groupId>com.sap.cloud.security</groupId>
diff --git a/java-security/src/test/java/com/sap/cloud/security/servlet/IasTokenAuthenticatorX509Test.java b/java-security/src/test/java/com/sap/cloud/security/servlet/IasTokenAuthenticatorX509Test.java
index fac26fed..46ba1d7f 100644
--- a/java-security/src/test/java/com/sap/cloud/security/servlet/IasTokenAuthenticatorX509Test.java
+++ b/java-security/src/test/java/com/sap/cloud/security/servlet/IasTokenAuthenticatorX509Test.java
@@ -80,14 +80,14 @@ class IasTokenAuthenticatorX509Test {
 		TokenAuthenticationResult response = cut.validateRequest(httpRequest, HTTP_RESPONSE);
 
 		assertThat(response.getUnauthenticatedReason())
-				.contains("Error during token validation: Certificate validation failed");
+				.contains("Error during token validation: Client certificate missing");
 		assertThat(response.isAuthenticated()).isFalse();
 
 		when(httpRequest.getHeader(FWD_CLIENT_CERT_HEADER)).thenReturn("");
 		TokenAuthenticationResult response2 = cut.validateRequest(httpRequest, HTTP_RESPONSE);
 
 		assertThat(response2.getUnauthenticatedReason())
-				.contains("Error during token validation: Certificate validation failed");
+				.contains("Error during token validation: Client certificate missing");
 		assertThat(response2.isAuthenticated()).isFalse();
 
 	}
@@ -100,7 +100,7 @@ class IasTokenAuthenticatorX509Test {
 		TokenAuthenticationResult response = cut.validateRequest(httpRequest, HTTP_RESPONSE);
 
 		assertThat(response.getUnauthenticatedReason())
-				.contains("Error during token validation: Certificate validation failed");
+				.contains("Error during token validation: Client certificate missing");
 		assertThat(response.isAuthenticated()).isFalse();
 	}
 
@@ -112,7 +112,7 @@ class IasTokenAuthenticatorX509Test {
 		TokenAuthenticationResult response = cut.validateRequest(httpRequest, HTTP_RESPONSE);
 
 		assertThat(response.getUnauthenticatedReason())
-				.contains("Error during token validation: Certificate validation failed");
+				.contains("Error during token validation: Certificate thumbprint validation failed");
 		assertThat(response.isAuthenticated()).isFalse();
 	}
 
diff --git a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidatorTest.java b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidatorTest.java
index ce67c67b..99590205 100644
--- a/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidatorTest.java
+++ b/java-security/src/test/java/com/sap/cloud/security/token/validation/validators/JwtX5tValidatorTest.java
@@ -23,10 +23,9 @@ import org.mockito.internal.util.collections.Sets;
 
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
-import java.util.Collections;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static com.sap.cloud.security.token.validation.validators.JwtX5tValidator.VALIDATION_FAILED;
+import static org.junit.jupiter.api.Assertions.*;
 
 class JwtX5tValidatorTest {
 
@@ -36,7 +35,6 @@ class JwtX5tValidatorTest {
 	private static X509Certificate x509;
 	private static final Token TOKEN = Mockito.mock(Token.class);
 	private static final JsonObject JSON_MOCK = Mockito.mock(JsonObject.class);
-	private static final String INVALID_MESSAGE = "Certificate validation failed";
 	private static final String X5T_VALIDATOR_DISABLED = "X5tValidator is not enabled";
 
 	@BeforeAll
@@ -55,90 +53,67 @@ class JwtX5tValidatorTest {
 	}
 
 	@Test
-	void validateToken_ValidToken_validX509() {
-		Token token = Token.create(tokenWithX5t);
-		SecurityContext.setClientCertificate(x509);
-		ValidationResult result = CUT.validate(token);
-		assertTrue(result.isValid());
+	void given_NoConfig() {
+		assertThrows(
+				IllegalArgumentException.class,
+				() -> new JwtX5tValidator(null),
+				"Service configuration must not be null");
 	}
 
 	@Test
-	void validateToken_ValidToken_invalidX509() {
-		Token token = Token.create(tokenWithX5t);
-		SecurityContext.setClientCertificate(null);
-		ValidationResult result = CUT.validate(token);
+	void given_NoToken() {
+		ValidationResult result = CUT.validate(null);
 		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
+		assertEquals("No token passed to validate certificate thumbprint", result.getErrorDescription());
 	}
 
 	@Test
-	void validateToken_validCnf_validX509_MultipleAud() {
+	void given_ValidToken_validX509() {
+		Token token = Token.create(tokenWithX5t);
 		SecurityContext.setClientCertificate(x509);
-		Mockito.when(TOKEN.getAudiences()).thenReturn(Sets.newSet("aud1", "aud2"));
-		Mockito.when(TOKEN.getClaimAsJsonObject(TokenClaims.CNF)).thenReturn(JSON_MOCK);
-		ValidationResult result = CUT.validate(TOKEN);
-		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
+		ValidationResult result = CUT.validate(token);
+		assertTrue(result.isValid());
 	}
 
 	@Test
-	void validateToken_validCnf_validX509_EmptyAud() {
-		SecurityContext.setClientCertificate(x509);
-		Mockito.when(TOKEN.getAudiences()).thenReturn(Collections.emptySet());
-		Mockito.when(TOKEN.getClaimAsJsonObject(TokenClaims.CNF)).thenReturn(JSON_MOCK);
-		ValidationResult result = CUT.validate(TOKEN);
+	void given_ValidToken_invalidX509() {
+		Token token = Token.create(tokenWithX5t);
+		SecurityContext.setClientCertificate(null);
+		ValidationResult result = CUT.validate(token);
 		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
+		assertEquals("Client certificate missing from SecurityContext", result.getErrorDescription());
 	}
 
 	@Test
-	void validateToken_InvalidCnf_validX509() {
+	void given_InvalidCnf_validX509() {
 		Token token = Token.create(tokenWithInvalidX5t);
 		SecurityContext.setClientCertificate(x509);
 		ValidationResult result = CUT.validate(token);
 		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
+		assertEquals(VALIDATION_FAILED, result.getErrorDescription());
 	}
 
 	@Test
-	void validateToken_InvalidCnf_invalidX509() {
+	void given_InvalidCnf_invalidX509() {
 		Token token = Token.create(tokenWithInvalidX5t);
 		SecurityContext.setClientCertificate(null);
 		ValidationResult result = CUT.validate(token);
 		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
+		assertEquals("Client certificate missing from SecurityContext", result.getErrorDescription());
 	}
 
 	@Test
-	void validateToken_NoCnf_validAud() {
+	void given_NoCnf_validAud() {
 		Mockito.when(JSON_MOCK.getAsString(TokenClaims.CNF_X5T)).thenReturn(null);
 		Mockito.when(TOKEN.getAudiences()).thenReturn(Sets.newSet("myClientId"));
 		ValidationResult result = CUT.validate(TOKEN);
 		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
-	}
-
-	@Test
-	void validateToken_NoCnf_MultipleAud() {
-		Mockito.when(JSON_MOCK.getAsString(TokenClaims.CNF_X5T)).thenReturn(null);
-		Mockito.when(TOKEN.getAudiences()).thenReturn(Sets.newSet("aud1", "aud2"));
-		ValidationResult result = CUT.validate(TOKEN);
-		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
-	}
-
-	@Test
-	void validateToken_NoCnf_EmptyAud() {
-		Mockito.when(JSON_MOCK.getAsString(TokenClaims.CNF_X5T)).thenReturn(null);
-		Mockito.when(TOKEN.getAudiences()).thenReturn(Collections.emptySet());
-		ValidationResult result = CUT.validate(TOKEN);
-		assertTrue(result.isErroneous());
-		assertEquals(INVALID_MESSAGE, result.getErrorDescription());
+		assertEquals("Token doesn't contain certificate thumbprint confirmation method", result.getErrorDescription());
 	}
 
-	@Disabled("until proofOfPossesion validator subchain is implemented")
+	@Disabled("until proofOfPossession validator subchain is implemented")
 	@Test
-	void validateToken_validatorDisabled() {
+	void given_validatorDisabled() {
 		Token token = Token.create(tokenWithX5t);
 		ValidationResult result = CUT.validate(token);
 		assertTrue(result.isErroneous());
diff --git a/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/HybridIdentityServicesAutoConfigurationTest.java b/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/HybridIdentityServicesAutoConfigurationTest.java
index c60cbe8b..82577abb 100644
--- a/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/HybridIdentityServicesAutoConfigurationTest.java
+++ b/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/HybridIdentityServicesAutoConfigurationTest.java
@@ -57,10 +57,10 @@ class HybridIdentityServicesAutoConfigurationTest {
 	}
 
 	@Test
-	void autoConfigurationDisabledForMultipleXsuaaServices() {
-		List<String> mt_properties = new ArrayList<>();
+	void autoConfigurationForIdentityAndSingleXsuaaService() {
 		WebApplicationContextRunner mt_runner;
 
+		List<String> mt_properties = new ArrayList<>();
 		mt_properties.add("sap.security.services.xsuaa[0].url:http://localhost");
 		mt_properties.add("sap.security.services.xsuaa[0].uaadomain:localhost");
 		mt_properties.add("sap.security.services.xsuaa[0].xsappname:theAppName");
@@ -74,7 +74,7 @@ class HybridIdentityServicesAutoConfigurationTest {
 
 		mt_runner.run(context -> {
 			assertFalse(context.containsBean("hybridJwtDecoder"));
-			assertNotNull(context.getBean("hybridJwtDecoderMultiXsuaaServices", HybridJwtDecoder.class));
+			assertTrue(context.containsBean("hybridJwtDecoderMultiXsuaaServices"));
 		});
 	}
 
@@ -104,6 +104,51 @@ class HybridIdentityServicesAutoConfigurationTest {
 		});
 	}
 
+	@Test
+	void autoConfigurationUsesDecoderForSingleXsuaaService() {
+		WebApplicationContextRunner mt_runner;
+
+		List<String> mt_properties = new ArrayList<>();
+		mt_properties.add("sap.security.services.xsuaa.url:http://localhost");
+		mt_properties.add("sap.security.services.xsuaa.uaadomain:localhost");
+		mt_properties.add("sap.security.services.xsuaa.xsappname:theAppName");
+		mt_properties.add("sap.security.services.xsuaa.clientid:xsuaacid");
+
+		mt_runner = new WebApplicationContextRunner()
+				.withPropertyValues(mt_properties.toArray(new String[0]))
+				.withConfiguration(AutoConfigurations.of(HybridIdentityServicesAutoConfiguration.class));
+
+		mt_runner.run(context -> {
+			assertTrue(context.containsBean("hybridJwtDecoder"));
+			assertFalse(context.containsBean("hybridJwtDecoderMultiXsuaaServices"));
+			assertEquals(context.getBean(HybridJwtDecoder.class),
+					context.getBean("hybridJwtDecoder"));
+		});
+	}
+
+	@Test
+	void autoConfigurationUsesDecoderForMultipleXsuaaServices() {
+		WebApplicationContextRunner mt_runner;
+
+		List<String> mt_properties = new ArrayList<>();
+		mt_properties.add("sap.security.services.xsuaa[0].url:http://localhost");
+		mt_properties.add("sap.security.services.xsuaa[0].uaadomain:localhost");
+		mt_properties.add("sap.security.services.xsuaa[0].xsappname:theAppName");
+		mt_properties.add("sap.security.services.xsuaa[0].clientid:xsuaacid");
+		mt_properties.add("sap.security.services.xsuaa[1].clientid:cid2");
+
+		mt_runner = new WebApplicationContextRunner()
+				.withPropertyValues(mt_properties.toArray(new String[0]))
+				.withConfiguration(AutoConfigurations.of(HybridIdentityServicesAutoConfiguration.class));
+
+		mt_runner.run(context -> {
+			assertFalse(context.containsBean("hybridJwtDecoder"));
+			assertTrue(context.containsBean("hybridJwtDecoderMultiXsuaaServices"));
+			assertEquals(context.getBean(HybridJwtDecoder.class),
+					context.getBean("hybridJwtDecoderMultiXsuaaServices"));
+		});
+	}
+
 	@Test
 	void userConfigurationCanOverrideDefaultBeans() {
 		runner.withUserConfiguration(UserConfiguration.class)
diff --git a/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfigurationTest.java b/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfigurationTest.java
index f9eed0dd..785c3c80 100644
--- a/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfigurationTest.java
+++ b/spring-security/src/test/java/com/sap/cloud/security/spring/autoconfig/XsuaaTokenFlowAutoConfigurationTest.java
@@ -72,9 +72,11 @@ class XsuaaTokenFlowAutoConfigurationTest {
 
 	@Test
 	void configures_xsuaaMtlsRestTemplate() {
-		runner
-				.withPropertyValues("sap.spring.security.xsuaa.flows.auto:true")
-				.withPropertyValues("sap.security.services.xsuaa.credential-type:x509")
+		runner = new ApplicationContextRunner()
+				.withConfiguration(AutoConfigurations.of(HybridIdentityServicesAutoConfiguration.class,
+						XsuaaTokenFlowAutoConfiguration.class))
+				.withPropertyValues("sap.security.services.xsuaa.certurl:https://domain.cert.auth.com")
+				.withPropertyValues("sap.security.services.xsuaa.clientid:cid")
 				.withPropertyValues("sap.security.services.xsuaa.certificate:" + cert)
 				.withPropertyValues("sap.security.services.xsuaa.key:" + key)
 				.run((context) -> {
@@ -90,7 +92,7 @@ class XsuaaTokenFlowAutoConfigurationTest {
 	}
 
 	@Test
-	void autoConfigurationDisabledWhenNoClientSecretIsGiven() {
+	void autoConfigurationDisabledWhenNoClientIdIsGiven() {
 		WebApplicationContextRunner mt_runner;
 
 		mt_runner = new WebApplicationContextRunner()
@@ -105,7 +107,7 @@ class XsuaaTokenFlowAutoConfigurationTest {
 		WebApplicationContextRunner mt_runner;
 
 		List<String> mt_properties = new ArrayList<>(properties);
-		mt_properties.add("sap.security.services.xsuaa[0].url:http://localhost");
+		mt_properties.add("sap.security.services.xsuaa[0].certurl:https://domain.cert.auth.com");
 		mt_properties.add("sap.security.services.xsuaa[0].clientid:cid");
 		mt_properties.add("sap.security.services.xsuaa[0].clientsecret:pwd");
 		mt_properties.add("sap.security.services.xsuaa[1].clientid:cid");
@@ -118,6 +120,26 @@ class XsuaaTokenFlowAutoConfigurationTest {
 		mt_runner.run(context -> assertTrue(context.containsBean("xsuaaTokenFlows")));
 	}
 
+	@Test
+	void configures_xsuaaMtlsRestTemplateForMultipleXsuaaServicesAsPrimary() {
+		WebApplicationContextRunner mt_runner;
+
+		List<String> mt_properties = new ArrayList<>(properties);
+		mt_properties.add("sap.security.services.xsuaa[0].url:http://localhost");
+		mt_properties.add("sap.security.services.xsuaa[0].clientid:cid");
+		mt_properties.add("sap.security.services.xsuaa[0].certificate:cert");
+		mt_properties.add("sap.security.services.xsuaa[0].key:key");
+		mt_properties.add("sap.security.services.xsuaa[1].clientid:cid");
+
+		mt_runner = new WebApplicationContextRunner()
+				.withPropertyValues(mt_properties.toArray(new String[0]))
+				.withConfiguration(AutoConfigurations.of(HybridIdentityServicesAutoConfiguration.class,
+						XsuaaTokenFlowAutoConfiguration.class));
+
+		mt_runner.run(context -> assertTrue(context.containsBean("xsuaaTokenFlows")));
+		mt_runner.run(context -> assertTrue(context.containsBean("mtlsRestOperations")));
+	}
+
 	@Test
 	void userConfigurationCanOverrideDefaultBeans() {
 		runner.withUserConfiguration(UserConfiguration.class)
diff --git a/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoderTest.java b/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoderTest.java
index 526ef650..9f8beacf 100644
--- a/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoderTest.java
+++ b/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/HybridJwtDecoderTest.java
@@ -5,7 +5,6 @@
  */
 package com.sap.cloud.security.spring.token.authentication;
 
-import com.sap.cloud.security.json.JsonParsingException;
 import com.sap.cloud.security.test.JwtGenerator;
 import com.sap.cloud.security.token.Token;
 import com.sap.cloud.security.token.TokenClaims;
@@ -27,11 +26,12 @@ import static org.mockito.Mockito.when;
 
 class HybridJwtDecoderTest {
 	JwtGenerator jwtGenerator = JwtGenerator.getInstance(IAS, "theClientId");
+	CombiningValidator<Token> combiningValidator;
 	HybridJwtDecoder cut;
 
 	@BeforeEach
 	void setup() {
-		CombiningValidator<Token> combiningValidator = Mockito.mock(CombiningValidator.class);
+		combiningValidator = Mockito.mock(CombiningValidator.class);
 		when(combiningValidator.validate(any())).thenReturn(ValidationResults.createValid());
 
 		cut = new HybridJwtDecoder(combiningValidator, combiningValidator);
@@ -61,7 +61,6 @@ class HybridJwtDecoderTest {
 
 	@Test
 	void decodeInvalidToken_throwsAccessDeniedException() {
-		CombiningValidator<Token> combiningValidator = Mockito.mock(CombiningValidator.class);
 		when(combiningValidator.validate(any())).thenReturn(ValidationResults.createInvalid("error"));
 		cut = new HybridJwtDecoder(combiningValidator, combiningValidator);
 		String encodedToken = jwtGenerator.createToken().getTokenValue();
@@ -80,13 +79,23 @@ class HybridJwtDecoderTest {
 
 	@Test
 	void decodeWithCorruptToken_throwsBadJwtException() {
-		String encodedToken = jwtGenerator
-				.withClaimValue(TokenClaims.EXPIRATION, "")
-				.createToken().getTokenValue();
-
 		assertThrows(BadJwtException.class, () -> cut.decode("Bearer e30="));
 		assertThrows(BadJwtException.class, () -> cut.decode("Bearer"));
 		assertThrows(BadJwtException.class, () -> cut.decode(null));
 		assertThrows(BadJwtException.class, () -> cut.decode("Bearerabc"));
 	}
+
+	@Test
+	void instantiateForXsuaaOnly() {
+		cut = new HybridJwtDecoder(combiningValidator, null);
+
+		// IAS token can't be validated
+		String encodedIasToken = jwtGenerator.createToken().getTokenValue();
+		assertThrows(BadJwtException.class, () -> cut.decode(encodedIasToken));
+
+		// XSUAA token can be validated
+		String encodedXsuaaToken = JwtGenerator.getInstance(XSUAA, "theClientId").createToken().getTokenValue();
+		assertEquals("theClientId", cut.decode(encodedXsuaaToken).getClaim(TokenClaims.AUTHORIZATION_PARTY));
+
+	}
 }
\ No newline at end of file
diff --git a/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilderTest.java b/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilderTest.java
index a8800c93..9d33f1f2 100644
--- a/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilderTest.java
+++ b/spring-security/src/test/java/com/sap/cloud/security/spring/token/authentication/JwtDecoderBuilderTest.java
@@ -38,21 +38,20 @@ class JwtDecoderBuilderTest {
 	}
 
 	@Test
-	void buildHybridWithoutConfiguration_IllegalArgumentException() {
-		assertThrows(IllegalArgumentException.class, () -> cut.build());
+	void buildWithoutConfiguration_IllegalStateException() {
+		assertThrows(IllegalStateException.class, () -> cut.build());
 	}
 
 	@Test
 	void buildHybridWithoutConfiguration() {
-		OAuth2ServiceConfiguration iasConfiguration = OAuth2ServiceConfigurationBuilder
+		OAuth2ServiceConfiguration configuration = OAuth2ServiceConfigurationBuilder
 				.forService(Service.IAS)
 				.withClientId("clientId")
 				.withProperty(CFConstants.URL, "https://domain.myauth.com")
-				// .withProperty(CFConstants.IAS.DOMAIN, "myauth.com")
 				.build();
 
-		cut.withIasServiceConfiguration(iasConfiguration);
-		cut.withXsuaaServiceConfiguration(iasConfiguration);
+		cut.withIasServiceConfiguration(configuration);
+		cut.withXsuaaServiceConfiguration(configuration);
 		cut.withValidationListener(Mockito.mock(ValidationListener.class));
 		JwtDecoder decoder = cut.build();
 		assertTrue(decoder instanceof HybridJwtDecoder);
diff --git a/spring-xsuaa-test/README.md b/spring-xsuaa-test/README.md
index 19d277ac..319d5813 100644
--- a/spring-xsuaa-test/README.md
+++ b/spring-xsuaa-test/README.md
@@ -31,7 +31,7 @@ This includes for example a `JwtGenerator` that generates JSON Web Tokens (JWT)
 <dependency>
     <groupId>com.sap.cloud.security.xsuaa</groupId>
     <artifactId>spring-xsuaa-test</artifactId>
-    <version>2.11.12</version>
+    <version>2.11.13</version>
     <scope>test</scope>
 </dependency>
 
diff --git a/spring-xsuaa-test/pom.xml b/spring-xsuaa-test/pom.xml
index 07e19403..9eaf9a43 100644
--- a/spring-xsuaa-test/pom.xml
+++ b/spring-xsuaa-test/pom.xml
@@ -9,7 +9,7 @@
 	<parent>
 		<groupId>com.sap.cloud.security.xsuaa</groupId>
 		<artifactId>parent</artifactId>
-		<version>2.11.12</version>
+		<version>2.11.13</version>
 	</parent>
 
 	<artifactId>spring-xsuaa-test</artifactId>
diff --git a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefaultTest.java b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefaultTest.java
index 164d4e74..8342a996 100644
--- a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefaultTest.java
+++ b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationDefaultTest.java
@@ -10,6 +10,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 import java.net.URI;
 
+import static com.sap.cloud.security.xsuaa.XsuaaServiceConfigurationDefault.VCAP_SERVICES_CREDENTIALS;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -52,8 +53,20 @@ public class XsuaaServiceConfigurationDefaultTest {
 
 	@Test
 	public void unsupportedMethods() {
-		assertThatThrownBy(() -> cut.hasProperty("")).isInstanceOf(UnsupportedOperationException.class);
-		assertThatThrownBy(() -> cut.getProperty("")).isInstanceOf(UnsupportedOperationException.class);
 		assertThatThrownBy(() -> cut.getProperties()).isInstanceOf(UnsupportedOperationException.class);
 	}
+
+	@Test
+	public void hasPropertyRequiresEnvironmentVar() {
+		assertThatThrownBy(() -> cut.hasProperty("clientid"))
+				.isInstanceOf(NullPointerException.class)
+				.hasMessageContaining(VCAP_SERVICES_CREDENTIALS);
+	}
+
+	@Test
+	public void getPropertyRequiresEnvironmentVar() {
+		assertThatThrownBy(() -> cut.getProperty("clientid"))
+				.isInstanceOf(NullPointerException.class)
+				.hasMessageContaining(VCAP_SERVICES_CREDENTIALS);
+	}
 }
\ No newline at end of file
diff --git a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationFromEnvTest.java b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationFromEnvTest.java
new file mode 100644
index 00000000..091ff536
--- /dev/null
+++ b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/XsuaaServiceConfigurationFromEnvTest.java
@@ -0,0 +1,41 @@
+package com.sap.cloud.security.xsuaa;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+
+import static com.sap.cloud.security.config.cf.CFConstants.CLIENT_ID;
+import static com.sap.cloud.security.config.cf.CFConstants.VCAP_SERVICES;
+import static com.sap.cloud.security.config.cf.CFConstants.XSUAA.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class XsuaaServiceConfigurationFromEnvTest {
+	XsuaaServiceConfigurationDefault cut;
+
+	@Rule
+	public final EnvironmentVariables environmentVariables = new EnvironmentVariables();
+
+	@Before
+	public void setup() {
+		environmentVariables.set(VCAP_SERVICES,
+				"{\"xsuaa\":[{\"credentials\":{\"apiurl\":\"https://api.mydomain.com\",\"tenantid\":\"tenant-id\",\"subaccountid\":\"subaccount-id\",\"clientid\":\"client-id\"},\"tags\":[\"xsuaa\"]}]}");
+		cut = new XsuaaServiceConfigurationDefault();
+	}
+
+	@Test
+	public void getProperty() {
+		assertThat(cut.getProperty(API_URL)).isEqualTo("https://api.mydomain.com");
+		assertThat(cut.getProperty(SUBACCOUNT_ID)).isEqualTo("subaccount-id");
+		assertThat(cut.getProperty(TENANT_ID)).isEqualTo("tenant-id");
+		assertThat(cut.getProperty(CLIENT_ID)).isEqualTo("client-id");
+		assertThat(cut.getProperty("unknownProp")).isNull();
+	}
+
+	@Test
+	public void hasProperty() {
+		assertThat(cut.hasProperty(API_URL)).isTrue();
+		assertThat(cut.hasProperty(SUBACCOUNT_ID)).isTrue();
+		assertThat(cut.hasProperty("unknownProp")).isFalse();
+	}
+}
\ No newline at end of file
diff --git a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfigurationTest.java b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfigurationTest.java
index b128af29..5a36537e 100644
--- a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfigurationTest.java
+++ b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfigurationTest.java
@@ -70,7 +70,7 @@ public class XsuaaAutoConfigurationTest {
 	}
 
 	@Test
-	public void configures_xsuaaMtlsRestTemplate() {
+	public void configures_xsuaaMtlsRestTemplateWithCredType() {
 		contextRunner
 				.withPropertyValues("spring.xsuaa.flows.auto:true")
 				.withPropertyValues("xsuaa.credential-type:x509")
@@ -84,6 +84,19 @@ public class XsuaaAutoConfigurationTest {
 				});
 	}
 
+	@Test
+	public void configures_xsuaaMtlsRestTemplate() {
+		contextRunner
+				.withPropertyValues("xsuaa.clientid:client")
+				.withPropertyValues("xsuaa.certificate:" + cert)
+				.withPropertyValues("xsuaa.key:" + key)
+				.withPropertyValues("xsuaa.certurl:https://domain.cert.authentication.sap.com")
+				.run((context) -> {
+					assertThat(context).hasSingleBean(RestOperations.class);
+					assertThat(context).hasBean("xsuaaMtlsRestOperations");
+				});
+	}
+
 	@Test
 	public void configures_xsuaaServiceConfiguration_withProperties() {
 		contextRunner.withClassLoader(new FilteredClassLoader(CloseableHttpClient.class))