The default CoreMedia Studio authentication process is implemented based on Spring Security. Due to this open standard it is easy 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 [CoreMedia 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-webapp
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 [CoreMedia Digital Experience Platform 8 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 file
/META-INF/coremedia/component-XYZ.xml
in the new component and include the
following import statement.
<import resource="classpath: /com/coremedia/rest/cap/authentication/editing-rest-security-base.xml"/>
Example 8.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 http
and the
authentication-manager
element. The http
element is the parent of all
functionality related to the web, the authentication-manager
holds the
configured authentication-provider
elements.
Your generic Spring security context for a redirect based SSO solution could look something like:
<security:http entry-point-ref="YOUR_ENTRY_POINT" auto-config="false"> <security:custom-filter position="FORM_LOGIN_FILTER" ref='YOUR_LOGIN_FILTER'/> <security:custom-filter position="LOGOUT_FILTER" ref='YOUR_LOGOUT_FILTER'/> <security:intercept-url pattern="/api/**" access="YOUR_AUTHORITY"/> <security:intercept-url pattern="/index.html" access="YOUR_AUTHORITY"/> <security:custom-filter .../> <security:session-management session-fixation-protection="newSession"/> <security:csrf request-matcher-ref="YOUR_CSRF_REQUEST_MATCHER"/> </security:http> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider ref='YOUR_AUTHENTICATION_PROVIDER'/> </security:authentication-manager>
Example 8.2. Spring Security context
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 (typically ROLE_XYZ
). This authority needs to match the one in
the intercept-url
elements of the Spring Security http
configuration.
The second requirement for the login procedure involves the authentication entry point
referenced in the http
configuration element. 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 can not handle redirects to pages reasonably. Unauthenticated REST calls should
trigger a 403 response instead which is then handled by Studio with a pop-up message. A
separate handling of REST calls and non REST calls can be achieved with a delegating entry point like
the following.
<bean id="delegatingEntryPoint" class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint"> <constructor-arg> <map> <entry key-ref="apiMatcher" value-ref="forbiddenAEP"/> </map> </constructor-arg> <property name="defaultEntryPoint" ref="SSO_SPECIFIC_ENTRY_POINT"/> </bean> <bean id="forbiddenAEP" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/> <bean id="apiMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> <constructor-arg value="/api/**"/> </bean>
Example 8.3. Delegating entry point
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 intercept-url
elements in the http
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 id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"> <constructor-arg value="LOGOUT_SUCCESS_TARGET"/> <constructor-arg> <list> <ref bean="capLogoutHandler"/> <ref bean="SSO_SPECIFIC_LOGOUT_HANDLER_IF_NEEDED"/> <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/> </list> </constructor-arg> <property name="logoutRequestMatcher" ref="logoutRequestMatcher"/> </bean>
Example 8.4. 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
While not required for the core functionality it is still highly recommended including a
csrf
and session-management
configuration in your http
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 session-management
configuration together with the
session-fixation-protection
attribute is used to explicitly enable the Spring
Security session fixation protection. The attribute value can safely be set to
newSession
.
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 simply extend the AbstractSpringSecurityCapUserFinder
that already has a CapConnection
available.
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 8.5. User finder
The custom user finder is enabled by replacing the Spring bean
springSecurityCapUserFinder
in the Spring context.
<customize:replace id="customSpringSecurityCapUserFinder" bean="springSecurityCapUserFinder"> <bean class="XYZSpringSecurityCapUserFinder" parent="abstractSpringSecurityCapUserFinder"/> </customize:replace>
Example 8.6. 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 configuration to your web.xml
:
<session-config> <tracking-mode>COOKIE</tracking-mode> </session-config>