close

Filter

loading table of contents...

Studio Developer Manual / Version 2204

Table Of Contents

10.3 Single Sign On Integration

The 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

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 CapConnections 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>

Search Results

Table Of Contents
warning

Your Internet Explorer is no longer supported.

Please use Mozilla Firefox, Google Chrome, or Microsoft Edge.