Studio Developer Manual / Version 2204
Table Of ContentsThe default CoreMedia Studio authentication process is implemented based on Spring Security. Due to this open standard it is possible to replace the standard authentication mechanism with a common redirect based SSO system like Atlassian Crowd or CAS. While the authentication process can be replaced, the CoreMedia Content Server still needs to have a matching user provider configured in order to perform a fine grained authorization. Please refer to the Content Server Manual for further details about user providers.
This documentation does not replace the SSO manufacturers manual about how to integrate with Spring Security. This section only covers CoreMedia Studio specific adjustments that need to be made to a generic integration.
Warning
Do not modify the authentication process and the Spring Security filter chain unless you know what you are doing. An improperly configured security context can cause severe security issues.
Custom Component
The first step to integrate with a single sign on system is to create a custom component as
replacement for the editing-rest-security-component
. The
editing-rest-security-component
contains the configuration for the default built-in
authentication process. It is not required anymore once there is a SSO integration in place. To
replace the component simply replace the editing-rest-security-component
dependency
in the pom.xml
of the studio-blueprint-component
with a dependency on the
new component.
For further details about component artifacts and how to create them, please refer to the section Application Architecture in the [Blueprint Developer Manual].
Generic Spring Security Context
The new component has to provide a Spring Security context that holds all the required
configuration to authenticate users against your SSO system. Simply create a
Spring @Configuration
class in the new component which is included by a
spring.factories
configuration and which extends
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
.
Also make sure, to include the following import statement.
@Configuration(proxyBeanMethods = false) @EnableWebSecurity @Import({EditingRestSecurityBaseConfiguration.class, EditingRestSecurityFilters.class}) public class EditingRestSecurityConfiguration extends WebSecurityConfigurerAdapter { ... }
Example 10.1. Import base context
Next, create a generic Spring Security context based on the SSO manufacturer's documentation.
Studio Spring Security Context
The core elements of a Spring Security context are the HttpSecurity
and the
AuthenticationManager
beans. The HttpSecurity
bean is the parent of all
functionality related to the web, the AuthenticationManager
holds the
configured AuthenticationProvider
. They are configured via the different
configure()
methods of WebSecurityConfigurerAdapter
.
Your generic Spring security configuration for a redirect-based SSO solution could look something like:
@Configuration @EnableWebSecurity @Import({EditingRestSecurityBaseConfiguration.class, EditingRestSecurityFilters.class}) public class EditingRestSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure( AuthenticationManagerBuilder auth) { auth.authenticationProvider(YOUR_AUTHENTICATION_PROVIDER); } @Override protected void configure(HttpSecurity http) throws Exception { http .addFilterAt(YOUR_LOGIN_FILTER, UsernamePasswordAuthenticationFilter.class) .addFilterAt(YOUR_LOGOUT_FILTER, LogoutFilter.class) .httpBasic().authenticationEntryPoint(YOUR_ENTRY_POINT) .and() .authorizeRequests() .antMatchers("/api/**").hasRole("YOUR_AUTHORITY") .antMatchers("/index.html").hasRole("YOUR_AUTHORITY") .antMatchers("/api/**") .access("hasRole('YOUR_AUTHORITY') or hasRole('ANONYMOUS')") .and() .sessionManagement().sessionAuthenticationStrategy(sessionFixationProtectionStrategy()) .and() .csrf().requireCsrfProtectionMatcher(YOUR_CSRF_REQUEST_MATCHER); } @Bean SessionFixationProtectionStrategy sessionFixationProtectionStrategy() { SessionFixationProtectionStrategy sessionFixationProtectionStrategy = new SessionFixationProtectionStrategy(); sessionFixationProtectionStrategy.setMigrateSessionAttributes(false); return sessionFixationProtectionStrategy; } ... }
Example 10.2. Spring Security context
The special intercept URL for the theme importer is only necessary if the theme importer is deployed with Studio in one web application. It takes care of its own API key based authentication and can coexist with the SSO integration.
Login
CoreMedia Studio only imposes very minimal constraints to the login process.
Depending on the chosen SSO system the login itself is either performed by a Spring Security
filter (internal login page) or an external system (external login page). The only requirement
for this part of the login is that at least one recognizable authority is granted to the
authenticated user. This authority needs to match the one in
the authorizeRequests()
elements of the Spring Security HttpSecurity
configuration.
The second requirement for the login procedure involves the authentication entry point
referenced in the HttpSecurity
configuration. The entry point implementation for a
redirect based SSO system usually does some sort of redirect to a login page. While this is
sensible behavior for a 'normal' request, it is not expected for Studio REST calls
which are XmlHttpRequests to a dedicated /api
path. The Studio REST
client cannot handle redirects to pages reasonably. Unauthenticated REST calls should
trigger a 403 response instead.
By default, the Studio client shows a local login page if it detects that no user is logged in.
Because this behavior is not appropriate in an SSO setting, you should set the Studio backend
property studio.loginUrl
to the SSO login page.
The Studio frontend will then forward the user to the login page,
if no current session can be found.
Alternatively, you can protect the web server that delivers the Studio frontend
in such a way that it redirects to the SSO login page immediately,
if no existing SSO session can be found.
The details of this procedure depend on you web server and SSO solution.
Authorization
In addition to the authorization happening in the Content Server Spring Security is
used to perform a pre-authorization at HTTP level. For a redirect based SSO system,
it is best practice to pre-authenticate all requests to the REST API (/api
path) and to the
index.html
. A set of authorizeRequests()
elements in the HttpSecurity
configuration checks for the granted authority that the SSO system assigns to authenticated
users.
Logout
CoreMedia Studio expects a logout listener to listen to POST requests the context relative path
/logout
. It has to trigger at least the default Spring Security
SecurityContextLogoutHandler
and the predefined capLogoutHandler
bean.
While the SecurityContextLogoutHandler
resets the security context, the
capLogoutHandler
ensures that all CapConnection
s for the current user
are closed and released.
The logout listener must not listen to GET requests as this might result in a CSRF
vulnerability. For simplicity reasons you can use the logoutRequestMatcher
bean
from the base security context.
A simple logout filter might look similar to this:
@Bean LogoutFilter logoutFilter(CapLogoutHandler capLogoutHandler, RequestMatcher logoutRequestMatcher) { LogoutFilter logoutFilter = new LogoutFilter( YOUR_LOGOUT_SUCCESS_HANDLER, capLogoutHandler, new SecurityContextLogoutHandler()); logoutFilter.setLogoutRequestMatcher(logoutRequestMatcher); return logoutFilter; }
Example 10.3. Logout filter
Depending on the chosen SSO system it might be required to add another SSO specific logout handler or define additional single sign out filters in the Spring Security filter chain.
Other Configuration
You need to include a csrf()
and a sessionManagement()
configuration
in your HttpSecurity
settings.
The csrf()
configuration is used to enable the Spring Security CSRF protection. It
must be enabled for all vulnerable HTTP verbs like POST, PUT, DELETE
, the
Studio client ensures that a valid token is included in the affected requests.
The sessionManagement()
configuration together with the
SessionFixationProtectionStrategy
bean attribute is used to explicitly enable the Spring
Security session fixation protection.
User Finder
After finishing the configuration of the Spring Security context, there is one last Studio specific step to do.
So far you have set up a Spring Security context that is using the default Spring Security
authentication providers and user detail services for your SSO system to authenticate users and
load user details. These user details are usually represented by a SSO specific details object
linked to the Spring Security Authentication
object.
While keeping the default implementations in the authentication process hugely simplifies the
SSO configuration, CoreMedia Studio still needs to know the matching com.coremedia.cap.user.User
for
the current SSO specific user details. Each individual Unified API operation has to be performed
in the name of the currently authenticated User
in order to be able to perform a
fine grained authorization in the CoreMedia Content Server. To do this mapping between SSO specific user
details and a User
for the chosen SSO system, you have to implement a
SpringSecurityUserFinder
.
The SpringSecurityCapUserFinder
interface consists of only one method that finds a
User
for a given Authentication
object. In order to write a finder for the
chosen SSO system you can extend the AbstractSpringSecurityCapUserFinder
.
public class XYZSpringSecurityCapUserFinder
extends AbstractSpringSecurityCapUserFinder
implements SpringSecurityCapUserFinder {
@Override
public User findCapUser(Authentication authentication) {
Object principal = authentication.getPrincipal();
if (principal instanceof XYZ) {
String username = GET_USER_NAME_FROM_USER_DETAILS;
return getCapConnection().getUserRepository()
.getUserByName(username, DOMAIN);
}
return null;
}
}
Example 10.4. User finder
The custom user finder is enabled by replacing the Spring bean
springSecurityCapUserFinder
in the Spring context.
@Bean(autowireCandidate = false) @Customize(value = "springSecurityCapUserFinder", mode = Customize.Mode.REPLACE) XYZSpringSecurityCapUserFinder xyzSpringSecurityCapUserFinder(CapConnection capConnection) { XYZSpringSecurityCapUserFinder xyzSpringSecurityCapUserFinder = new XYZSpringSecurityCapUserFinder(); xyzSpringSecurityCapUserFinder.setCapConnection(capConnection); return xyzSpringSecurityCapUserFinder; }
Example 10.5. Enable user finder
Session Tracking Mode
In order to prevent the JSESSIONID
from appearing as an URL parameter it is recommended to add the
following Spring Boot confiuration property: server.servlet.session.tracking-modes=cookie
.
If using WAR deployment add the configuration to your web.xml
file:
<session-config> <tracking-mode>COOKIE</tracking-mode> </session-config>