Make sure that you've imported the Product List sample application (Spring) as part of this Exercise.
Within Eclipse IDE you should see the product-list
project in the Project Explorer View.
- Build the project in Eclipse (
Context Menu -> Run As -> Maven install
) -> Result: BUILD FAILURE
The build fails as the
ControllerTests
JUnit test expects that a bean ofXsuaaServiceConfiguration
class exists and allGET
endpoints of the Product-List are secured.
To secure the application we have to add XSUAA Spring Security library to the classpath. This library enhances the spring-security project. As of version 5 of spring-security, this includes the OAuth resource-server functionality. A Spring boot application needs a security configuration class that enables the resource server and configures authentication with XSUAA as OAuth Authorization Server using JWT tokens.
-
Get the current version of the SAP XSUAA Integration Security library from Maven Central.
-
Add the following dependency to your
pom.xml
file:<dependency> <groupId>com.sap.cloud.security.xsuaa</groupId> <artifactId>xsuaa-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency>
-
After you've added the Maven dependencies, don't forget to update your Maven project (
ALT-F5
)! -
Note: the following test-dependencies are already added to the
pom.xml
file:<dependency> <groupId>com.sap.cloud.security.xsuaa</groupId> <artifactId>spring-xsuaa-test</artifactId> <version>2.0.0</version> <scope>test</scope> </dependency> <dependency> <groupId>com.sap.cloud.security.xsuaa</groupId> <artifactId>spring-xsuaa-mock</artifactId> <version>2.0.0</version> <scope>test</scope> </dependency>
- Update
com.sap.cp.cf.demoapps.SecurityConfiguration.java
class including the following scope checks and offline token validations.
package com.sap.cp.cf.demoapps;
import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration;
import com.sap.cloud.security.xsuaa.token.TokenAuthenticationConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.jwt.Jwt;
import static org.springframework.http.HttpMethod.GET;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final XsuaaServiceConfiguration xsuaaServiceConfiguration;
@Autowired
public SecurityConfiguration(XsuaaServiceConfiguration xsuaaServiceConfiguration) {
this.xsuaaServiceConfiguration = xsuaaServiceConfiguration;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests()
.antMatchers(GET, "/actuator/**").anonymous() // accepts unauthenticated user (w/o JWT)
.antMatchers(GET, "/", "/products/**").hasAuthority("read") // checks scope $XSAPPNAME.read
.antMatchers(GET, "/productsByParam").authenticated() // TODO: apply scope check at method level using @PreAuthorize
.anyRequest().denyAll() // denies anything not configured above
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(getJwtAuthoritiesConverter());
}
Converter<Jwt, AbstractAuthenticationToken> getJwtAuthoritiesConverter() {
TokenAuthenticationConverter converter = new TokenAuthenticationConverter(xsuaaServiceConfiguration);
converter.setLocalScopeAsAuthorities(true);
return converter;
}
}
After the previous step still one JUnit test will fail as the /productsByParam
endpoint is not protected with scope checks.
With @EnableGlobalMethodSecurity
annotation (see SecurityConfiguration
class) Spring Method Security is enabled. Now you can apply fine granular authorization checks on method level.
- In the
ProductRepo
class annotate thefindByName(String)
method with:... and fix the missing import issue.@PreAuthorize("hasAuthority('read')")
- Build the project in Eclipse (
Context Menu -> Run As -> Maven install
) -> Result: BUILD SUCCESS- Or, alternatively build the project on the console with the following commands:
D: cd D:\Files\Session\SEC364\teched2019-cloud-cf-product-list-teched2019\samples\spring mvn clean install
- Or, alternatively build the project on the console with the following commands:
- Finally, make sure that the folder
D:\Files\Session\SEC364\teched2019-cloud-cf-product-list-teched2019\samples\spring\target
contains aproduct-list.jar
file.
- Github XSUAA Spring Security library:
https://github.com/SAP/cloud-security-xsuaa-integration - XSUAA Token Client and Token Flow API:
https://github.com/SAP/cloud-security-xsuaa-integration/tree/master/token-client
-
© 2019 SAP SE
![Continue Exercise: Secure application Continue Exercise](/SAP-archive/teched2019-cloud-cf-product-list/raw/teched2019/docs/img/arrow_left.png)