Repository: SAP/cloud-security-xsuaa-integration (java)

Issue:
Possibility of disabling xsuaaMtlsRestOperations bean if XsuaaServiceConfiguration is not provided 
**Question Summary**
- client library: `spring-xsuaa` version `2.11.1`
- Environment: Cloud Foundry

We are currently in the process of changing our xsuaa bindings to `x509` credentials for our spring applications. We are also using CAP as a framework, and we have discovered a small issue regarding the `XsuaaAutoConfiguration`. For the `x509` case, a bean [`xsuaaMtlsRestOperations`](https://github.com/SAP/cloud-security-xsuaa-integration/blob/2.11.1/spring-xsuaa/src/main/java/com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration.java#L104) is configured which requires a parameter of type `XsuaaServiceConfiguration`. Usually, this is not a problem but with CAP there is use case to run a Cloud Foundry task for database migration on the java application which is executed with security disabled (because it does not expose any endpoints). You can check in their docs [here](https://cap.cloud.sap/docs/java/multitenancy#deploy-main-method). In this scenario, CAP does not provide any bean of type `XsuaaServiceConfiguration` and the application startup fails with the following exception:

```
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'xsuaaMtlsRestOperations' defined in class path resource [com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration.class]: 
Unsatisfied dependency expressed through method 'xsuaaMtlsRestOperations' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
	...
```

Would it be an option for you to only provide a bean `xsuaaMtlsRestOperations` if `XsuaaServiceConfiguration` is provided, or in other words to make `xsuaaMtlsRestOperations` conditional on bean `XsuaaServiceConfiguration`?

If you have any further questions, let me know.

Regards,
Florian

Pull request:
Xsuaa Autoconfig refinement
closes #739

Patch:
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 8d878093..77c99562 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -11,15 +11,19 @@ on:
 
 jobs:
   build:
-
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        java-version: [ 8, 11 ]
+    name: Build with Java ${{ matrix.java-version }}
 
     steps:
       - uses: actions/checkout@v2
-      - name: Set up JDK 1.8
-        uses: actions/setup-java@v1
+      - name: Set up JDK ${{ matrix.java-version }}
+        uses: actions/setup-java@v2
         with:
-          java-version: 1.8
+          distribution: 'adopt'
+          java-version: ${{ matrix.java-version }}
       - name: Build with Maven
         run: mvn -B install --file pom.xml
       - name: Run integration tests
diff --git a/env/pom.xml b/env/pom.xml
index 45e90bcd..ccdcc977 100644
--- a/env/pom.xml
+++ b/env/pom.xml
@@ -130,8 +130,8 @@
                 <artifactId>maven-pmd-plugin</artifactId>
             </plugin>
             <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>findbugs-maven-plugin</artifactId>
+                <groupId>com.github.spotbugs</groupId>
+                <artifactId>spotbugs-maven-plugin</artifactId>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
diff --git a/java-api/pom.xml b/java-api/pom.xml
index b8b5e49e..480a42d3 100644
--- a/java-api/pom.xml
+++ b/java-api/pom.xml
@@ -24,8 +24,8 @@
 			<scope>provided</scope>
 		</dependency>
 		<dependency>
-			<groupId>com.google.code.findbugs</groupId>
-			<artifactId>jsr305</artifactId>
+			<groupId>com.github.spotbugs</groupId>
+			<artifactId>spotbugs-annotations</artifactId>
 		</dependency>
 		<dependency>
 			<groupId>javax.servlet</groupId>
@@ -112,8 +112,8 @@
 				<artifactId>maven-pmd-plugin</artifactId>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>findbugs-maven-plugin</artifactId>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-maven-plugin</artifactId>
 			</plugin>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
diff --git a/java-security/README.md b/java-security/README.md
index ee04e6f3..7c647232 100644
--- a/java-security/README.md
+++ b/java-security/README.md
@@ -186,10 +186,15 @@ For the integration of different Identity Services the [`TokenAuthenticator`](/j
 This validator is not part of the default `CombiningValidator`, it needs to be added manually to `JwtValidatorBuilder` to use it. 
 It can be done in the following manner:
 ```java
-JwtValidatorBuilder.getInstance(OAuth2ServiceConfiguration)
-    .with(new JwtX5tValidator(OAuth2ServiceConfiguration))
+JwtValidatorBuilder.getInstance(oAuth2ServiceConfiguration)
+    .with(new JwtX5tValidator(oAuth2ServiceConfiguration))
     .build();
 ```
+Or it can be used as a standalone `Validator`, by creating a new instance of it and calling `JwtX5tValidator.validate(Token token)` method with the token to be validated as a method's parameter. See [here](#get-information-from-token) how to get a token from `SecurityContext`
+```java
+JwtX5tValidator validator = new JwtX5tValidator(oAuth2ServiceConfiguration);
+ValidationResult result = validator.validate(token);
+```
 
 #### Common Issues 
 In case of invalid response i.e 401 or 403 error codes, check application error logs for detailed messages. 
diff --git a/java-security/pom.xml b/java-security/pom.xml
index d6eb6f02..8a372d08 100644
--- a/java-security/pom.xml
+++ b/java-security/pom.xml
@@ -117,7 +117,7 @@
 		<dependency>
 			<groupId>com.github.stefanbirkner</groupId>
 			<artifactId>system-lambda</artifactId>
-			<version>1.2.0</version>
+			<version>1.2.1</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
@@ -177,8 +177,8 @@
 				<artifactId>maven-pmd-plugin</artifactId>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>findbugs-maven-plugin</artifactId>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-maven-plugin</artifactId>
 			</plugin>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
diff --git a/pom.xml b/pom.xml
index 0d8511a6..fdf7fd6e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,7 +64,7 @@
 		<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.13</reactor.version>
-		<log4j2.version>2.17.0</log4j2.version>
+		<log4j2.version>2.17.1</log4j2.version>
 		<slf4j.api.version>1.7.32</slf4j.api.version> <!--see also here http://www.slf4j.org/faq.html#changesInVersion18 -->
 		<org.json.version>20211205</org.json.version>
 		<google.jsr305.version>3.0.2</google.jsr305.version>
@@ -81,6 +81,9 @@
 		<assertj.version>3.21.0</assertj.version>
 		<reactor.test.version>3.4.13</reactor.test.version>
 		<wiremock.version>2.32.0</wiremock.version>
+		<javax.annotation.version>1.3.2</javax.annotation.version>
+		<spotbugs.annotations.version>4.5.2</spotbugs.annotations.version>
+		<spotbugs.version>4.5.2.0</spotbugs.version>
 		<skipTests>false</skipTests>
 		<jacoco.skip>${skipTests}</jacoco.skip>
 	</properties>
@@ -182,6 +185,11 @@
 				</exclusion>
 			</exclusions>
 			</dependency>
+			<dependency>
+				<groupId>javax.annotation</groupId>
+				<artifactId>javax.annotation-api</artifactId>
+				<version>${javax.annotation.version}</version>
+			</dependency>
 			<!-- logging -->
 			<dependency>
 				<groupId>org.apache.logging.log4j</groupId>
@@ -211,9 +219,9 @@
 				<version>${org.json.version}</version>
 			</dependency>
 			<dependency>
-				<groupId>com.google.code.findbugs</groupId>
-				<artifactId>jsr305</artifactId>
-				<version>${google.jsr305.version}</version>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-annotations</artifactId>
+				<version>${spotbugs.annotations.version}</version>
 			</dependency>
 			<dependency>
 				<groupId>org.apache.httpcomponents</groupId>
@@ -346,17 +354,19 @@
 							</executions>
 						</plugin>
 						<plugin>
-							<groupId>org.codehaus.mojo</groupId>
-							<artifactId>findbugs-maven-plugin</artifactId>
-							<version>3.0.5</version>
+							<groupId>com.github.spotbugs</groupId>
+							<artifactId>spotbugs-maven-plugin</artifactId>
+							<version>${spotbugs.version}</version>
 							<configuration>
 								<skip>${skipTests}</skip>
+								<effort>Max</effort>
+								<threshold>Low</threshold>
 							</configuration>
 							<executions>
 								<execution>
 									<phase>verify</phase>
 									<goals>
-										<goal>findbugs</goal>
+										<goal>spotbugs</goal>
 									</goals>
 								</execution>
 							</executions>
diff --git a/spring-security/pom.xml b/spring-security/pom.xml
index 454454cb..49186205 100644
--- a/spring-security/pom.xml
+++ b/spring-security/pom.xml
@@ -122,8 +122,8 @@
 				<artifactId>maven-pmd-plugin</artifactId>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>findbugs-maven-plugin</artifactId>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-maven-plugin</artifactId>
 			</plugin>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
diff --git a/spring-xsuaa-mock/pom.xml b/spring-xsuaa-mock/pom.xml
index a394afe8..edbc41c2 100644
--- a/spring-xsuaa-mock/pom.xml
+++ b/spring-xsuaa-mock/pom.xml
@@ -109,8 +109,8 @@
 				<artifactId>maven-pmd-plugin</artifactId>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>findbugs-maven-plugin</artifactId>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-maven-plugin</artifactId>
 			</plugin>
 		</plugins>
 	</build>
diff --git a/spring-xsuaa/pom.xml b/spring-xsuaa/pom.xml
index 3ad8f962..e963aa46 100644
--- a/spring-xsuaa/pom.xml
+++ b/spring-xsuaa/pom.xml
@@ -33,6 +33,10 @@
 			</exclusions>
 			<scope>provided</scope>
 		</dependency>
+		<dependency>
+			<groupId>javax.annotation</groupId>
+			<artifactId>javax.annotation-api</artifactId>
+		</dependency>
 		<dependency>
 			<groupId>org.apache.logging.log4j</groupId>
 			<artifactId>log4j-to-slf4j</artifactId>
@@ -86,7 +90,6 @@
 			<optional>true</optional>
 		</dependency>
 
-
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
@@ -200,8 +203,8 @@
 				<artifactId>maven-pmd-plugin</artifactId>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>findbugs-maven-plugin</artifactId>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-maven-plugin</artifactId>
 			</plugin>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
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 43434daf..0eced4a5 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
@@ -13,10 +13,7 @@ import com.sap.cloud.security.xsuaa.extractor.TokenUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.*;
 import org.springframework.context.annotation.*;
 import org.springframework.core.type.AnnotatedTypeMetadata;
 import org.springframework.security.oauth2.jwt.Jwt;
@@ -86,6 +83,7 @@ public class XsuaaAutoConfiguration {
 	@Bean
 	@Conditional({ OnNotX509CredentialTypeCondition.class })
 	@ConditionalOnMissingBean
+	@ConditionalOnBean(XsuaaServiceConfiguration.class)
 	public RestOperations xsuaaRestOperations() {
 		LOGGER.warn("In productive environment provide a well configured client secret based RestOperations bean");
 		return new RestTemplate();
@@ -101,6 +99,7 @@ public class XsuaaAutoConfiguration {
 	@ConditionalOnProperty(prefix = "xsuaa", name = "credential-type", havingValue = "x509")
 	@ConditionalOnMissingBean
 	@ConditionalOnClass(name = "org.apache.http.impl.client.CloseableHttpClient")
+	@ConditionalOnBean(XsuaaServiceConfiguration.class)
 	public RestOperations xsuaaMtlsRestOperations(XsuaaServiceConfiguration xsuaaServiceConfiguration) {
 		LOGGER.warn("In productive environment provide a well configured certificate based RestOperations bean");
 		return SpringHttpClient.getInstance().create(xsuaaServiceConfiguration.getClientIdentity());
diff --git a/token-client/pom.xml b/token-client/pom.xml
index 87634389..530cd434 100644
--- a/token-client/pom.xml
+++ b/token-client/pom.xml
@@ -44,8 +44,8 @@
 			<artifactId>json</artifactId>
 		</dependency>
 		<dependency>
-			<groupId>com.google.code.findbugs</groupId>
-			<artifactId>jsr305</artifactId>
+			<groupId>com.github.spotbugs</groupId>
+			<artifactId>spotbugs-annotations</artifactId>
 		</dependency>
 		<dependency>
 			<groupId>com.github.ben-manes.caffeine</groupId>
@@ -144,8 +144,8 @@
 				<artifactId>maven-pmd-plugin</artifactId>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>findbugs-maven-plugin</artifactId>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-maven-plugin</artifactId>
 			</plugin>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>


Test patch:
diff --git a/java-security-it/src/test/java/com/sap/cloud/security/test/integration/XsuaaMultipleBindingsIntegrationTest.java b/java-security-it/src/test/java/com/sap/cloud/security/test/integration/XsuaaMultipleBindingsIntegrationTest.java
index e3c84223..e7f5c6e7 100644
--- a/java-security-it/src/test/java/com/sap/cloud/security/test/integration/XsuaaMultipleBindingsIntegrationTest.java
+++ b/java-security-it/src/test/java/com/sap/cloud/security/test/integration/XsuaaMultipleBindingsIntegrationTest.java
@@ -31,7 +31,7 @@ public class XsuaaMultipleBindingsIntegrationTest {
 	@Test
 	public void createToken_integrationTest_tokenValidation() {
 		Token token = rule.getPreconfiguredJwtGenerator().createToken();
-		OAuth2ServiceConfiguration configuration = Environments.readFromInput(ClassLoader.class.getResourceAsStream("/vcap_services-multiple.json")).getXsuaaConfiguration();
+		OAuth2ServiceConfiguration configuration = Environments.readFromInput(XsuaaMultipleBindingsIntegrationTest.class.getResourceAsStream("/vcap_services-multiple.json")).getXsuaaConfiguration();
 		CombiningValidator<Token> tokenValidator = JwtValidatorBuilder.getInstance(configuration).build();
 
 		ValidationResult result = tokenValidator.validate(token);
diff --git a/spring-xsuaa-test/pom.xml b/spring-xsuaa-test/pom.xml
index 442c8ca3..0305d428 100644
--- a/spring-xsuaa-test/pom.xml
+++ b/spring-xsuaa-test/pom.xml
@@ -87,8 +87,8 @@
 				<artifactId>maven-pmd-plugin</artifactId>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>findbugs-maven-plugin</artifactId>
+				<groupId>com.github.spotbugs</groupId>
+				<artifactId>spotbugs-maven-plugin</artifactId>
 			</plugin>
 		</plugins>
 	</build>
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 e7e10b18..b128af29 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
@@ -5,13 +5,9 @@
  */
 package com.sap.cloud.security.xsuaa.autoconfiguration;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-
+import com.sap.cloud.security.xsuaa.DummyXsuaaServiceConfiguration;
+import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration;
+import com.sap.cloud.security.xsuaa.XsuaaServiceConfigurationDefault;
 import org.apache.commons.io.IOUtils;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.junit.Before;
@@ -30,13 +26,13 @@ import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.web.client.RestOperations;
 import org.springframework.web.client.RestTemplate;
 
-import com.sap.cloud.security.xsuaa.DummyXsuaaServiceConfiguration;
-import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration;
-import com.sap.cloud.security.xsuaa.XsuaaServiceConfigurationDefault;
-
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = { XsuaaAutoConfiguration.class, DummyXsuaaServiceConfiguration.class })
 public class XsuaaAutoConfigurationTest {
@@ -118,9 +114,18 @@ public class XsuaaAutoConfigurationTest {
 	}
 
 	@Test
-	public void serviceConfigurationDisabledByDisableDefaultPropertySourceProperty() {
+	public void serviceConfigurationDisabled_DisableDefaultPropertySourceProperty_mtls() {
 		contextRunner.withPropertyValues("spring.xsuaa.disable-default-property-source:true")
-				.run((context) -> assertThat(context).doesNotHaveBean("xsuaaServiceConfiguration"));
+				.withPropertyValues("xsuaa.credential-type:x509")
+				.run((context) -> assertThat(context).doesNotHaveBean("xsuaaServiceConfiguration")
+						.doesNotHaveBean("mtlsRestOperations"));
+	}
+
+	@Test
+	public void serviceConfigurationDisabled_DisableDefaultPropertySourceProperty_nonMtls() {
+		contextRunner.withPropertyValues("spring.xsuaa.disable-default-property-source:true")
+				.run((context) -> assertThat(context).doesNotHaveBean("xsuaaServiceConfiguration")
+						.doesNotHaveBean("xsuaaRestOperations"));
 	}
 
 	@Test