This migration guide is a step-by-step guide explaining how to replace the spring-xsuaa with this spring-security Security client library.
To use the new SAP CP spring-security client library the dependencies declared in maven pom.xml need to be updated.
Make sure, that you add the dependencies that are documented here.
Now you are ready to remove the spring-xsuaa client library by deleting the following dependencies from the pom.xml:
| groupId | artifactId |
|---|---|
| com.sap.cloud.security.xsuaa | spring-xsuaa |
| com.sap.cloud.security.xsuaa | xsuaa-spring-boot-starter |
After the dependencies have been changed, the spring security configuration needs some adjustments as well.
In case you have configured your TokenAuthenticationConverter with setLocalScopeAsAuthorities(true) then you can use the auto-configured converter as documented here, which initializes the XsuaaTokenAuthorizationConverter.
Before
Converter<Jwt, AbstractAuthenticationToken> customJwtAuthenticationConverter() {
TokenAuthenticationConverter converter = new TokenAuthenticationConverter(xsuaaServiceConfiguration);
converter.setLocalScopeAsAuthorities(true);
return converter;
}After
@Autowired
Converter<Jwt, AbstractAuthenticationToken> authConverter;spring-security automatically maps the VCAP_SERVICES credentials to Spring properties. Please note that the prefix has changed from xsuaa.* to sap.security.services.xsuaa or sap.security.services.xsuaa[0] in case of multiple xsuaa service bindings. Please find a sample property file here.
Before
@Value("${xsuaa.clientid})After
@Value("${sap.security.services.xsuaa.clientid}) // new prefixBefore
import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration;
...
@Autowired
XsuaaServiceConfiguration xsuaaServiceConfiguration;After
import com.sap.cloud.security.spring.config.XsuaaServiceConfiguration; // new import
...
@Autowired
XsuaaServiceConfiguration xsuaaServiceConfiguration;Before
import com.sap.cloud.security.xsuaa.XsuaaCredentials;
import com.sap.cloud.security.xsuaa.XsuaaServiceConfigurationCustom;
...
@Bean
@ConfigurationProperties("vcap.services.<<name of your xsuaa instance of plan application>>.credentials")
public XsuaaCredentials xsuaaCredentials() {
return new XsuaaCredentials(); // primary Xsuaa service binding, e.g. application
}
@Bean
@ConfigurationProperties("vcap.services.<<name of your xsuaa instance of plan broker>>.credentials")
public XsuaaCredentials brokerCredentials() {
return new XsuaaCredentials(); // secondary Xsuaa service binding, e.g. broker
}
@Bean
public XsuaaServiceConfiguration customXsuaaConfig() {
return new XsuaaServiceConfigurationCustom(xsuaaCredentials());
}After
import com.sap.cloud.security.spring.config.XsuaaServiceConfigurations; // new import
...
@Autowired
XsuaaServiceConfigurations xsuaaServiceConfigurations;💡 application plan is served as main configuration, you can get it using
xsuaaServiceConfigurations.get(0).
Other configurations, e.g. of plan broker, can be accessed with index > 0.
You may have code parts that use the SpringSecurityContext to get the token. Just update the import from:
import com.sap.cloud.security.xsuaa.token.SpringSecurityContext;to
import com.sap.cloud.security.spring.token.SpringSecurityContext; // new importYou may have code parts that use the Token interface to access details from the token. You need to update the import from:
import com.sap.cloud.security.xsuaa.token.Token;to
import com.sap.cloud.security.token.Token; // new import - preferred
// or
import com.sap.cloud.security.token.XsuaaTokenComp; // new importThe Token interface from java-api provides methods that serves access to details of a token, independent whether it is issued by xsuaa or by identity service. That's why the new Token interface isn't compatible to the Token interface from spring-xsuaa client library.
java-api provides also the AccessToken sub-interface to access xsuaa specific claims, in case of access tokens issued by the xsuaa service.
Alternatively - for compatibility, XsuaaTokenComp class can be used to decorate the AccessToken interface, which implements almost all methods of com.sap.cloud.security.xsuaa.token.Token (spring-xsuaa) interface.
It is provided in an extra module. This maven dependency needs to be provided additionally:
<dependency>
<groupId>com.sap.cloud.security.xsuaa</groupId>
<artifactId>spring-security-compatibility</artifactId>
<version>2.13.7</version>
</dependency>Token xsuaaToken = XsuaaTokenComp.createInstance(SpringSecurityContext.getAccessToken());
xsuaaToken.getCloneServiceInstanceId();💡
createInstanceraises anIllegalArgumentExceptionruntime exception if the token isn't issued by xsuaa service. :bulb:getAuthorities, as well as theorg.springframework.security.core.userdetails.UserDetailsis not implemented byXsuaaTokenComp.
The table below gives an overview of the methods that are not directly available in the new Token interface, but can be accessed via the XsuaaTokenComp decorator class.
Details
com.sap.cloud.security.xsuaa.token.Token methods |
Xsuaa only? | Workaround in spring.security (com.sap.cloud.security.token.Token) |
|---|---|---|
getSubaccountId |
X | Available via AccessToken interface. |
getSubdomain |
X | getAttributeFromClaimAsString(EXTERNAL_ATTRIBUTE, EXTERNAL_ATTRIBUTE_ZDN) |
getGrantType |
X | getGrantType().toString(). |
getLogonName |
(X) | getClaimAsString("user_name"). 💡 the name differs between the two services. |
getOrigin |
X | getClaimAsString(TokenClaims.XSUAA.ORIGIN). |
getGivenName |
getClaimAsString(TokenClaims.GIVEN_NAME). 💡 no support for SAML 2.0 - XSUAA mapping. |
|
getFamilyName |
getClaimAsString(TokenClaims.FAMILY_NAME). 💡 no support for SAML 2.0 - XSUAA mapping. |
|
getEmail |
getClaimAsString(TokenClaims.EMAIL). 💡 no support for SAML 2.0 - XSUAA mapping. |
|
getXSUserAttribute |
X | getAttributeFromClaimAsStringList(TokenClaims.XSUAA.XS_USER_ATTRIBUTES, attributeName) |
getAdditionalAuthAttribute |
X | getAttributeFromClaimAsString("az_attr", attributeName) |
getCloneServiceInstanceId |
X | getAttributeFromClaimAsString(TokenClaims.XSUAA.EXTERNAL_ATTRIBUTE, "serviceinstanceid") |
getAppToken |
getTokenValue |
|
getScopes |
X | getClaimAsStringList(TokenClaims.XSUAA.SCOPES) |
getExpiration() |
getExpiration() and for convenience isExpired() |
|
getUsername() |
getPrincipal() |
💡 In case the
Xsuaa only?flag is set, the method returns "null" in case of Id token from identity service.
💡 In case of Id token from identity service, theTokencan neither be casted toAccessTokennor toXsuaaToken. A cast is possible in case of:Service.XSUAA.equals(token.getService()).
The runtime type of com.sap.cloud.security.xsuaa.token.Token is com.sap.cloud.security.xsuaa.token.XsuaaToken, which provides additional methods that can be used to extract data from the token since it is a subclass of
org.springframework.security.oauth2.jwt.Jwt.
The following table gives an overview about the most prominent used Jwt methods and how they can be mapped:
org.springframework.security.oauth2.jwt.Jwt methods |
Workaround in spring.security (using com.sap.cloud.security.token.Token) |
|---|---|
getClaimAsString |
getClaimAsString |
getClaimAsStringList |
getClaimAsStringList |
containsClaim |
hasClaim |
getClaims |
getClaims |
getHeaders |
getHeaders |
getClaimAsInstant |
getClaimAsJsonObject().getAsInstant() |
In your unit test you might want to generate jwt tokens and have them validated. The new
java-security-test library provides its own JwtGenerator.
See the java-security-test documentation for more details, also on how to leverage JUnit 5 extensions.
The new security library requires the following key value pairs to configure the jwt validators. You can use the defaults specified within the java-security-test testing library.
sap:
security:
services:
xsuaa:
xsappname: xsapp!t0815
uaadomain: localhost
clientid: sb-clientId!t0815
clientsecret: pwd
url: http://localhost
identity:
clientid: sb-clientId!t0815
domain: localhost
url: http://localhostWhen your code compiles again you should first check that all your unit tests are running again. If you can test your application locally make sure it is still working and finally test the application in cloud foundry.
In case you face issues with the migration steps check this troubleshoot guide for known issues and file a new github issue in case youe problem is not yet described in the section. With that you can help us to improve this migration guide!