Fork me on GitHub

Introduction

CAS (Central Authentication Service) is a single sign-on protocol for the web. Its purpose is to permit a user to access multiple applications while providing their credentials (such as user identifier and password) only once. It also allows Web applications to authenticate users without gaining access to a user's security credentials, such as a password. The name CAS also refers to a software package that implements this protocol.
This document presents the different operations to enable CAS with Silverpeas :

  • Installing the JDK
  • Installing a CAS Server on Tomcat
  • Enabling CAS Authentication on Silverpeas

For the rest of this document ServerA will be the CAS Server, and ServerB will be the Silverpeas Server.

For more information on CAS you can read Wikipedia's article or go to CAS website.

Certificates Configuration

JDK

You will install the latest JDK from SUN: download it from here.
It will be used by the Apache Tomcat server who will host the CAS server.

Certificates

To generate certificates for each server we will use the JDK tool: keytool. The following command will create a keystore in C:\Java/keystore.jks:

keytool -genkey -keystore C:\Java\keystore.jks -alias tomcat -keypass changeit -keyalg RSA

Use the password changeit.
Enter all the requested information. Note that you must enter the name of the server as the 'first and last name'.
So for the CAS server it should be ServerA.

Now we need to repeat this operation for ServerB.

Trusting each others

Once the server is running, you can use our utility : Certificat Importer to add the certificate to the trustore.

java -jar CertificateImporter.jar serverB:8443 changeit C:\Java\keystore.jks

Now we need to repeat this operation for ServerB.

Configuration of Tomcat as a CAS Server

Installing Tomcat

Download and install the last release of Tomcat from the Apache Tomcat website. Don't forget to define the environment variables: JAVA_HOME and CATALINA_HOME.
Now, you can edit the file server.xml and allow the SSL connector by uncommenting the following element and configuring the paths to the keystore an trustore :

<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
<Connector port="8443" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" disableUploadTimeout="true"
           acceptCount="100" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS"
           keystoreFile="C:/Java/keystore.jks"
           keystorePass="changeit"
           truststoreFile="C:/Java/keystore.jks"/>

Installing the CAS Server

Download the latest CAS Server package from the CAS Website. Extract the WAR file from the archive in cas-server-3.4.2\modules and copy into in $CATALINA_HOME/webapps. Rename the WAR into cas.war.

Configuring the authentication mecanism

The CAS Server is configured using the file deployerConfigContext.xml in the directory $CATALINA_HOME/webapps/cas/WEB-INF.

Default Mode

By default, the authentication checks that the password matches the login. This is configured with the following deployerConfigContext.xml :

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

  <bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl">
    <property name="credentialsToPrincipalResolvers">
      <list>
        <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
        <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
      </list>
    </property>

    <property name="authenticationHandlers">
      <list>
        <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
              p:httpClient-ref="httpClient" />
        <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
      </list>
    </property>
  </bean>
  
  <bean id="userDetailsService" class="org.springframework.security.userdetails.memory.InMemoryDaoImpl">
    <property name="userMap">
      <value></value>
    </property>
  </bean>

  <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao">
    <property name="backingMap">
      <map>
        <entry key="uid" value="uid" />
        <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
        <entry key="groupMembership" value="groupMembership" />
      </map>
    </property>
  </bean>

  <bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl" />
</beans>

JDBC Mode

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  <bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl">
    <property name="credentialsToPrincipalResolvers">
      <list>
        <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
        <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
      </list>
    </property>
    <property name="authenticationHandlers">
      <list>
        <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
              p:httpClient-ref="httpClient" />
        <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
          <property name="dataSource" ref="dataSource" />
          <property name="sql"
                    value="select password from login_table_name where lower(login_column_name) = lower(?)" />
        </bean>
      </list>
    </property>
  </bean>

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName">
      <value>org.postgresql.Driver</value>
    </property>
    <property name="url">
      <value>jdbc:postgresql://serverB:5432/database_name</value>
    </property>
    <property name="username">
      <value>database_username</value>
    </property>
    <property name="password">
      <value>database_password</value>
    </property>
  </bean>

  <bean id="userDetailsService" class="org.springframework.security.userdetails.memory.InMemoryDaoImpl">
    <property name="userMap">
      <value></value>
    </property>
  </bean>

  <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao">
    <property name="backingMap">
      <map>
        <entry key="uid" value="uid" />
        <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
        <entry key="groupMembership" value="groupMembership" />
      </map>
    </property>
  </bean>

  <bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl" />
</beans>

The previous example uses a connection to PostgreSQL (configure the datasource bean according to your RDBMS). Don't forget to add the JDBC driver into your WEB-INF/lib directory.

LDAP Mode

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

  <bean id="contextSource" class="org.jasig.cas.adaptors.ldap.util.AuthenticatedLdapContextSource">
    <property name="pooled" value="true"/>
    <property name="urls">
      <list>
        <value>ldap://ldap_server_name:ldap_port</value>
      </list>
    </property>
    <property name="userName" value="uid=admin,ou=system"/>
    <property name="password" value="secret"/>
    <property name="baseEnvironmentProperties">
      <map>
        <entry>
          <key>
            <value>java.naming.security.authentication</value>
          </key>
          <value>simple</value>
        </entry>
      </map>
    </property>
  </bean>

  <bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl">
    <property name="credentialsToPrincipalResolvers">
      <list>
        <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
        <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
      </list>
    </property>
    <property name="authenticationHandlers">
      <list>
        <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
              p:httpClient-ref="httpClient" />
        <bean class="org.jasig.cas.adaptors.ldap.FastBindLdapAuthenticationHandler" >
          <property name="filter" value="uid=%u,ou=Users,dc=example,dc=com" />
          <property name="contextSource" ref="contextSource" />
        </bean>
      </list>
    </property>
  </bean>

  <bean id="userDetailsService" class="org.springframework.security.userdetails.memory.InMemoryDaoImpl">
    <property name="userMap">
      <value></value>
    </property>
  </bean>

  <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao">
    <property name="backingMap">
      <map>
        <entry key="uid" value="uid" />
        <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
        <entry key="groupMembership" value="groupMembership" />
      </map>
    </property>
  </bean>

  <bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl" />
</beans>

You need to configure your LDAP parameters, and to download the Jar file cas-server-support-ldap and add it to your WEB-INF/lib directory.

Customizing the CAS pages

You can customize les pages of the CAS Server by editing the JSPs in $CATALINA_HOME/webapps/cas/WEB-INF/view/jsp/default/ui or the stylesheets in $CATALINA_HOME/webapps/cas/css.

Configuring Silverpeas

Configuring the keystore

On the Silverpeas Sever (ServerB). Go and edit the file $SILVERPEAS_HOME/initialize/systemSettings.properties.
Set the various parameters (supposing that the keystore you have generated following the documentation is in C:\Java\keystore.jks) :

  • javax.net.ssl.trustStore=C:\\Java\\keystore.jks
  • ssl.keystore=C:\\Java\\keystore.jks
  • ssl.keystore.password=changeit

Configuration the servlet filter

You need to enable the CAS Servlet Filter. To do this edit the $JBOSS_HOME/server/deploy/silverpeas.ear/war-ic.war/WEB-INF/web.xml.
and add the following configuration :

  <context-param>
    <param-name>serverName</param-name>
    <param-value>http://localhost:8000</param-value>
  </context-param>

  ...

  <filter>
    <filter-name>CAS Authentication Filter</filter-name>
    <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
    <init-param>
      <param-name>casServerLoginUrl</param-name>
      <param-value>https://ServerA:8443/cas/login</param-value>
    </init-param>
  </filter>
  <filter>
    <filter-name>CAS Validation Filter</filter-name>
    <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
    <init-param>
      <param-name>casServerUrlPrefix</param-name>
      <param-value>https://ServerA:8443/cas</param-value>
    </init-param>
  </filter>

  ...

  <filter-mapping>
    <filter-name>CAS Authentication Filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>CAS Validation Filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
        

You can find more informations from CAS website: Sample web.xml, Configuration details and CAS Java Client.

Configuring the Login page

Edit the file in $SILVERPEAS_HOME/properties/org/silverpeas/lookAndFeel/generalLook.properties, update the parameter loginPage like this :

loginPage = /silverpeas/AuthenticationServlet
          

Activating the realm

Edit the file in $SILVERPEAS_HOME/properties/org/silverpeas/authentication/autDomainSP.properties, set the parameter autServer0.enabled to true and thus enable the CAS authentication :

autServer0.type=org.silverpeas.authentication.AuthenticationCAS
autServer0.enabled=true
autServer0.SQLJDBCUrl=jdbc:postgresql://localhost:5432/SilverpeasV5
autServer0.SQLAccessLogin=postgres
autServer0.SQLAccessPasswd=postgres
autServer0.SQLDriverClass=org.postgresql.Driver
autServer0.SQLUserTableName=st_user
autServer0.SQLUserLoginColumnName=login
          

Since the authentication was performed beforehand, the class AuthenticationCAS just check for an existing user in the user table of Silverpeas.

Now we need to define the domainId that is going to be used by CAS. By default it is 0 to match the previous configuration but this can be configured by editing the file in $SILVERPEAS_HOME/properties/org/silverpeas/authentication/settings/authenticationSettings.properties, and add the following parameter like this :

cas.authentication.domainId=0
          

At last, to coclude the configuration you can setup a logout page for Silverpeas to be called after the logout has been performed by adding the entry logout.page to the file $SILVERPEAS_HOME/properties/org/silverpeas/authentication/settings/authenticationSettings.properties like this :

logout.page=myLogoutPage.jsp