SAP / cloud-security-services-integration-library

Integration libraries and samples for authenticating users and clients bound to XSUAA authentication and authorization service or Identity authentication service.
Apache License 2.0
151 stars 136 forks source link

Migration to Spring 5.x and xsuaa-spring-boot-starter from java-container-security #537

Closed Victor-Fioneer closed 3 years ago

Victor-Fioneer commented 3 years ago

Hi dear xsuaa team, Our SAP Fioneer team has been following the migration guide to move to spring-xsuaa:2.9.0: https://github.com/SAP/cloud-security-xsuaa-integration/blob/master/spring-xsuaa/Migration_JavaContainerSecurityProjects.md

We encountered the same authorization issues as described here: https://github.com/SAP/cloud-security-xsuaa-integration/issues/362 But the solutions like adding @SpringBootApplication @componentscan({"com.sap.cloud.security.xsuaa","com.sap.cloud.security.xsuaa.","org.springframework.security.oauth."}) and XsuaaServiceConfiguration xsuaaServiceConfiguration() { return new XsuaaServiceConfigurationDefault(); } In the SecurityConfiguration file didn't help.

Dealing with 2 problems: 1) Token token = SpringSecurityContext.getToken();

Either we get null authentication and "Access forbidden" in SpringSecurityContext: static public Token getToken() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

    if (authentication == null) {
        throw new AccessDeniedException("Access forbidden: not authenticated");
    }

or after switching from com.sap.cloud.security.xsuaa:spring-xsuaa to com.sap.cloud.security.xsuaa:xsuaa-spring-boot-starter 2) org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tokenUtil' defined in class path resource [com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration$XsuaaServiceAutoConfiguration.class]: Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [com.sap.cloud.security.xsuaa.extractor.TokenUtil] from ClassLoader [LazyStopLazyStopWebappClassLoader

The Maven tree looks like this: [INFO] +- com.sap.cloud.security.xsuaa:xsuaa-spring-boot-starter:jar:2.9.0:compile [INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.5.0:compile [INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.5.0:compile [INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.3:compile [INFO] | | | | - ch.qos.logback:logback-core:jar:1.2.3:compile [INFO] | | | - org.slf4j:jul-to-slf4j:jar:1.7.30:compile [INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile [INFO] | | - org.yaml:snakeyaml:jar:1.28:compile [INFO] | +- com.sap.cloud.security.xsuaa:spring-xsuaa:jar:2.9.0:compile [INFO] | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.14.1:compile [INFO] | | | +- org.slf4j:slf4j-api:jar:1.7.25:compile [INFO] | | | - org.apache.logging.log4j:log4j-api:jar:2.14.1:compile [INFO] | | +- com.sap.cloud.security.xsuaa:api:jar:2.9.0:compile [INFO] | | +- com.sap.cloud.security.xsuaa:token-client:jar:2.9.0:compile [INFO] | | | +- com.sap.cloud.security:java-api:jar:2.9.0:compile [INFO] | | | +- org.json:json:jar:20210307:compile [INFO] | | | - com.google.code.findbugs:jsr305:jar:3.0.2:compile [INFO] | | - commons-io:commons-io:jar:2.9.0:compile [INFO] | - org.springframework.boot:spring-boot-starter-security:jar:2.5.0:compile [INFO] | - org.springframework:spring-aop:jar:5.3.7:compile [INFO] +- org.springframework.boot:spring-boot:jar:2.3.12.RELEASE:compile [INFO] +- org.springframework.boot:spring-boot-autoconfigure:jar:2.3.12.RELEASE:compile [INFO] +- io.projectreactor:reactor-core:jar:3.3.17.RELEASE:compile [INFO] +- org.reactivestreams:reactive-streams:jar:1.0.3:compile [INFO] +- org.springframework:spring-web:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-webmvc:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-beans:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-context:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-core:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework.security:spring-security-web:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-oauth2-jose:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-oauth2-resource-server:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-jwt:jar:1.1.1.RELEASE:compile [INFO] +- org.springframework.security:spring-security-config:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-core:jar:5.3.9.RELEASE:compile [INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.10-sap-02:compile [INFO] | - com.fasterxml.jackson.core:jackson-annotations:jar:2.9.10:compile [INFO] +- com.fasterxml.jackson.core:jackson-core:jar:2.9.10:compile [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided [INFO] +- commons-lang:commons-lang:jar:2.6:compile [INFO] +- commons-logging:commons-logging:jar:1.2:compile [INFO] - com.sap.fs.pro:json:jar:600.2.0-upgrades-SNAPSHOT:compile

SecurityConfig.java: ... @Configuration @EnableWebSecurity(debug = true) @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) @ComponentScan({"com.sap.cloud.security.xsuaa","com.sap.cloud.security.xsuaa.","org.springframework.security.oauth."}) public class UAASecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean XsuaaServiceConfiguration xsuaaServiceConfiguration() { return new XsuaaServiceConfigurationDefault(); }

@Autowired
XsuaaServiceConfiguration xsuaaServiceConfiguration;

@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session is created by approuter
        .and()
            .authorizeRequests()
            .antMatchers("/*").authenticated()
        .and()
            .oauth2ResourceServer()
            .bearerTokenResolver(new IasXsuaaExchangeBroker(xsuaaServiceConfiguration))
            .jwt()
            .jwtAuthenticationConverter(getJwtAuthenticationConverter());
    // @formatter:on
}

}

ApplicationInitializer.java: public class SecurityWebApplicationInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) {
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(UAASecurityConfiguration.class);
    servletContext.addListener(new ContextLoaderListener(rootContext));
}

}

SecurityConfig.java and AppInitializer.java are based on the examples in bulletinboard app: https://github.com/SAP-samples/cloud-bulletinboard-ads/tree/585c7a1a9763c627009fda03a6424e0328df3c5a/src/main/java/com/sap/bulletinboard/ads

Thanks, Would appreciate if anyone can shed some light on how to tackle those issues. Victor

nenaraab commented 3 years ago

Hi @Victor-Fioneer can you please update the above description with

nenaraab commented 3 years ago

This issue

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tokenUtil' defined in class path resource [com/sap/cloud/security/xsuaa/autoconfiguration/XsuaaAutoConfiguration$XsuaaServiceAutoConfiguration.class]: Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [com.sap.cloud.security.xsuaa.extractor.TokenUtil] from ClassLoader [LazyStopLazyStopWebappClassLoader

seems to be an issue with class loader, class couldn't be loaded... But maybe its an issue in your context with the @PostConstruct annotation. In order to check that, you may try with version Version 2.8.7 instead of 2.9.0

Victor-Fioneer commented 3 years ago

Thank you you for your suggestion about version 2.8.7. It helped to resolve "Failed to introspect Class [com.sap.cloud.security.xsuaa.extractor.TokenUtil]" Also I noticed ClassNotFound issues deeper in the trace and fixed them by adding spring-security-oauth2-core and nimbus-jose-jwt in the pom.xml

org.springframework.security spring-security-oauth2-core 5.3.9.RELEASE
    <dependency>
        <groupId>com.nimbusds</groupId>
        <artifactId>nimbus-jose-jwt</artifactId>
        <version>9.10</version>
    </dependency>

Now the SecurityConfiguration.java file is failing at this line .bearerTokenResolver(new IasXsuaaExchangeBroker(xsuaaServiceConfiguration)) With an exception:

                                    Caused by: java.lang.NullPointerException: while trying to invoke the method java.lang.String.length() of a null object loaded from field java.net.URI$Parser.input of an object loaded from local variable 'this'
                                        at java.net.URI$Parser.parse(URI.java:3041)
                                        at java.net.URI.<init>(URI.java:588)
                                        at java.net.URI.create(URI.java:850)
                                        at com.sap.cloud.security.xsuaa.client.XsuaaDefaultEndpoints.<init>(XsuaaDefaultEndpoints.java:34)
                                        at com.sap.cloud.security.xsuaa.extractor.IasXsuaaExchangeBroker.<init>(IasXsuaaExchangeBroker.java:38)
                                at com.sap.cloud.security.xsuaa.extractor.IasXsuaaExchangeBroker.<init>(IasXsuaaExchangeBroker.java:43)

Looking at line 34 of XsuaaDefaultEndpoints.java public XsuaaDefaultEndpoints(String baseUri) { this(URI.create(baseUri)); } It seems like baseUri is null. Is there an explicit way to initialize it?

nenaraab commented 3 years ago

Hi @Victor-Fioneer can you please send me your VCAP_SERVICES via mail?

Victor-Fioneer commented 3 years ago

@nenaraab VCAP_SERVICES is below with key values modified:

"VCAP_SERVICES" : { "xsuaa" : [ { "name" : "victor-dt-uaa", "label" : "xsuaa", "tags" : [ "xsuaa" ], "plan" : "default", "credentials" : { "tenantmode" : "dedicated", "clientid" : "sb-icdtordev-dev-victor-dt", "verificationkey" : "-----BEGIN PUBLIC KEY-----JHREVDXY&...-----END PUBLIC KEY-----", "xsappname" : "icdtordev-dev-victor-dt", "identityzone" : "uaa", "identityzoneid" : "uaa", "clientsecret" : "bJh...==", "url" : "https://vlgsp60f0f.wdf.sap.corp:30032/uaa-security" } } ] }

nenaraab commented 3 years ago

Hi @Victor-Fioneer honestly i'm unable to see any issue with your VCAP_SERVICES. "default" plan is supported by XsuaaServicePropertySourceFactory t and should not cause any issue during setup, and "url" should be loaded by XsuaaServiceConfigurationDefault.

Can you please check, whether your XsuaaServiceConfiguration Bean is instantiated properly?

Furthermore, in case you are not interested into ias2xsuaa token exchange you can comment this line: .bearerTokenResolver(new IasXsuaaExchangeBroker(xsuaaServiceConfiguration))

Kind regards, Nena

Further References

Victor-Fioneer commented 3 years ago

Thank you, @nenaraab , for your continued help with our upgrade issues. As I was investigating XsuaaServiceConfiguration bean loading, I tried adding WebAppContextConfig class from the bulletinboard example

@Configuration @EnableWebMvc @ComponentScan(basePackages = "com.sap.fs.pro.security.configuration") // includes sub packages public class WebAppContextConfig {

@Bean
@Profile("cloud")
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
    // make environment variables available for Spring's @Value annotation
    return new PropertySourcesPlaceholderConfigurer();
}

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
    return new MethodValidationPostProcessor();
}

}

as well as adding Nimbus to address a class not found issue.

com.nimbusds nimbus-jose-jwt 9.10

All of that led to a new Spring issue: UnsatisfiedDependencyException: Error creating bean with name 'requestMappingHandlerAdapter' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Unsatisfied dependency expressed through method 'requestMappingHandlerAdapter' parameter 2; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mvcValidator' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.validation.Validator]: Factory method 'mvcValidator' threw exception; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean]: Unresolvable class definition; nested exception is java.lang.NoClassDefFoundError: javax/validation/ParameterNameProvider at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray

Even with adding validation-api to the Maven dependency tree. javax.validation:validation-api:jar:2.0.1.Final The issue peresists.

Updated Maven tree is below. I am just puzzled why validation-api:jar:2.0.1.Final is not having effect. I made sure the jar is present in WEB-INF/lib. [INFO] +- com.sap.cloud.security.xsuaa:xsuaa-spring-boot-starter:jar:2.9.0:compile [INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.5.0:compile [INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.5.0:compile [INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.3:compile [INFO] | | | | - ch.qos.logback:logback-core:jar:1.2.3:compile [INFO] | | | - org.slf4j:jul-to-slf4j:jar:1.7.30:compile [INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile [INFO] | | - org.yaml:snakeyaml:jar:1.28:compile [INFO] | +- com.sap.cloud.security.xsuaa:spring-xsuaa:jar:2.9.0:compile [INFO] | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.14.1:compile [INFO] | | | +- org.slf4j:slf4j-api:jar:1.7.25:compile [INFO] | | | - org.apache.logging.log4j:log4j-api:jar:2.14.1:compile [INFO] | | +- com.sap.cloud.security.xsuaa:api:jar:2.9.0:compile [INFO] | | +- com.sap.cloud.security.xsuaa:token-client:jar:2.9.0:compile [INFO] | | | +- com.sap.cloud.security:java-api:jar:2.9.0:compile [INFO] | | | +- org.json:json:jar:20210307:compile [INFO] | | | - com.google.code.findbugs:jsr305:jar:3.0.2:compile [INFO] | | - commons-io:commons-io:jar:2.9.0:compile [INFO] | - org.springframework.boot:spring-boot-starter-security:jar:2.5.0:compile [INFO] | - org.springframework:spring-aop:jar:5.3.7:compile [INFO] +- org.springframework.boot:spring-boot:jar:2.3.12.RELEASE:compile [INFO] +- org.springframework.boot:spring-boot-autoconfigure:jar:2.3.12.RELEASE:compile [INFO] +- io.projectreactor:reactor-core:jar:3.3.17.RELEASE:compile [INFO] +- org.reactivestreams:reactive-streams:jar:1.0.3:compile [INFO] +- org.springframework:spring-web:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-webmvc:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-beans:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-context:jar:5.2.15.RELEASE:compile [INFO] +- org.springframework:spring-core:jar:5.2.15.RELEASE:compile [INFO] +- com.nimbusds:nimbus-jose-jwt:jar:9.10:compile [INFO] | - com.github.stephenc.jcip:jcip-annotations:jar:1.0-1:compile [INFO] +- javax.validation:validation-api:jar:2.0.1.Final:compile [INFO] +- org.springframework.security:spring-security-web:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-oauth2-core:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-oauth2-jose:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-oauth2-resource-server:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-jwt:jar:1.1.1.RELEASE:compile [INFO] +- org.springframework.security:spring-security-config:jar:5.3.9.RELEASE:compile [INFO] +- org.springframework.security:spring-security-core:jar:5.3.9.RELEASE:compile [INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.10-sap-02:compile [INFO] | - com.fasterxml.jackson.core:jackson-annotations:jar:2.9.10:compile [INFO] +- com.fasterxml.jackson.core:jackson-core:jar:2.9.10:compile [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided [INFO] +- commons-lang:commons-lang:jar:2.6:compile [INFO] +- commons-logging:commons-logging:jar:1.2:compile

Overall, I feel I need another approach than the current trial and error. What would you suggest as a minimum set of classes to have:

nenaraab commented 3 years ago

Hi @Victor-Fioneer it seems that your setup looks similar to the one of our microservice course (bulletinboard app). Its a Spring (but not Spring-boot) application.

You can not copy 1:1 as this project is totally outdated, but maybe it helps to get a solid setup. Furthermore, i guess - as its no Spring-boot application its not possible to leverage the autoconfigurations, that are provided with starters... and you need to create the beans by yourself.

Kind regards, Nena

nenaraab commented 3 years ago

Hi @Victor-Fioneer,

there is no migration path for pure java applications that only like to leverage spring security. An overview about supported migration path is given here: https://github.com/SAP-samples/teched2020-DEV263

Kind regards, Nena