Published using Google Docs
Configuring Alfresco for SSO with CAS and Securing Tomcat
Updated automatically every 5 minutes

Table of Contents

Author: Martin Bergljung

Introduction

Configuration with CAS on same Tomcat as Alfresco Server

Configuring SSL for Alfresco Tomcat

Tell Alfresco JRE about the Self-sign certificate

Installing CAS in the same Tomcat instance as Alfresco

Configuring CAS SSO for Alfresco Explorer

Configuring CAS SSO for Alfresco Share

Putting the CAS server on a separate host

Setting up the new CAS server

Installing CAS on a separate host

Generating a self-signed certificate for the Tomcat server that runs CAS

Testing the CAS installation

Letting the CAS host know about the Alfresco host

Updating the Alfresco installation and removing the CAS server

Letting the Alfresco host know about the CAS host

Remove CAS from the Tomcat server that runs Alfresco

Make sure the Alfresco host can get through to the CAS host on port 8443

Updating the Login CAS Web Script

Updating the web.xml for the Alfresco Explorer and the Alfresco Share web applications

Generating a new self-signed certificate for the Tomcat server that runs Alfresco

Importing the CAS Host certificate into the Alfresco Host Java runtime environment

Importing the Alfresco Host certificate into the CAS Host Java runtime environment

Introduction

In my last Alfresco project I had to implement Single Sign On (SSO) with a CAS server (http://www.jasig.org/cas). This turned out to be a bit trickier than I initially thought. I found some resources about the subject that looked promising:

http://holisticsecurity.wordpress.com/2011/02/19/web-sso-between-liferay-and-alfresco-with-cas-and-penrose-part-22/ 

http://akselsarchitecture.blogspot.com/2010/09/cas-sso-for-alfresco-33-and-share.html 

http://translate.google.com/translate?u=http://blog.atolcd.com/%3Fp%3D115&sl=fr&tl=en 

I started off using the files provided by the http://akselsarchitecture.blogspot.com/2010/09/cas-sso-for-alfresco-33-and-share.html link and set about to test it with Alfresco 3.4. I pretty quickly got Alfresco Explorer to work with CAS Server 3.4.6. This was because CAS does not require you to use SSL in this scenario. When it came to getting it to work with Alfresco Share (that authenticates via Alfresco Repo/Explorer – proxy authentication) it was a different story.

I could not get it to work no matter what I did. If I would have looked closer at the URLs in some of the files that I downloaded I would have seen that https was used in a lot of places. This was the key to the problem. Because Share would be using the proxy authentication mechanism provided by CAS, it required both CAS and the Alfresco server to be configured to support SSL.

A link that I found useful in explaining proxy authentication scenarios was this one:

https://wiki.jasig.org/display/CAS/Proxy+CAS+Walkthrough 

Now let’s walk through from scratch how to get this working. The best thing you can do is start locally, with Alfresco and CAS running in the same Tomcat instance, and get it to work there before moving on to a deployment with CAS and Alfresco servers on different hosts.

Configuration with CAS on same Tomcat as Alfresco Server

This section shows how to configure CAS support when the CAS server runs on the same Apache Tomcat as the Alfresco server.

Configuring SSL for Alfresco Tomcat

As part of the proxy authentication scenario the CAS server will call back to the Alfresco server and this call need to be secure via SSL. To configure support for https in Alfresco Tomcat (Version 6.0.29 in the Alfresco 3.4 Enterprise that I am using) do as follows:

  1. Enable the SSL HTTP/1.1 Connector on port 8443, this is done in file /alfresco/tomcat/conf/server.xml:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"

maxThreads="150" scheme="https" secure="true"

        keystoreFile="C:/Users/mbergljung/.keystore" keystorePass="changeit"

clientAuth="false" sslProtocol="TLS" />

  1. Create a certificate keystore (the keystoreFile points to it) for Tomcat to use and generate a self-signed certificate at the same time for localhost. The following command will generate a .keystore file in user home, make sure to use password changeit everywhere:

C:\>keytool -genkey -alias tomcat -keyalg RSA

Enter keystore password:

Re-enter new password:

What is your first and last name?

  [Unknown]:  localhost

What is the name of your organizational unit?

  [Unknown]:  Dev

What is the name of your organization?

  [Unknown]:  Ixxus

What is the name of your City or Locality?

  [Unknown]:  London

What is the name of your State or Province?

  [Unknown]:  London

What is the two-letter country code for this unit?

  [Unknown]:  UK

Is CN=localhost, OU=Dev, O=Ixxus, L=London, ST=London, C=UK correct?

  [no]:  Yes

Enter key password for <tomcat>

        (RETURN if same as keystore password):

The first and last name need to be the domain of the Tomcat server, in our case it will be localhost as we will be running both Alfresco and CAS locally in the same Tomcat instance, this means that we later on have to specify all URLs as http(s)://localhost:....

If you have specified an incorrect first and last name (i.e. domain) then you will see an error message such as the following:

java.security.cert.CertificateException: No name matching localhost found

SSL uses asymmetric encryption (i.e. public key cryptography) and because we are using a self-signed certificate we will get a warning message in the browser to accept/trust or ignore the certificate. On the other hand, a program with no human interaction, like CAS calling Alfresco, will not give us this possibility but instead just throw an exception like the following:

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

This error message means that the Public Key Infrastructure (PKI) cannot find a path from the self-signed certificate for our local Tomcat to one of the Certificate Authorities (CA) certificates. Meaning we could be talking to any local Tomcat server, really.

We will see in the next section how we can import the self-signed certificate into any Java runtime environment that wants to talk to Tomcat on localhost (in this case it would be only local JREs).

  1. Disable the APR library loader in the tomcat configuration file /alfresco/tomcat/conf/server.xml:

<!--APR library loader. Documentation at /docs/apr.html

  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />-->

        

This is because a bug in Tomcat 6.0.2x where it starts up the Apache Portable Runtime (APR)

engine to listen on 8443 when that port is already taken by the standard blocking IO connector that we defined in step 1, an error like the following can be seen:

java.lang.Exception: Socket bind failed: [730048] Only one usage of each socket address (protocol/network address/port) is normally permitted.  

        at org.apache.tomcat.util.net.AprEndpoint.init(AprEndpoint.java:647)

        at org.apache.tomcat.util.net.AprEndpoint.start(AprEndpoint.java:754)

        at org.apache.coyote.http11.Http11AprProtocol.start(Http11AprProtocol.java:137)

Ok that should do it; Alfresco Tomcat is now enabled for secure connections.

Tell Alfresco JRE about the Self-sign certificate

The self-signed certificate used by Tomcat needs to be imported into the Java Runtime environment that Alfresco uses. In my case I installed the full Alfresco package with JRE, MySQL, Tomcat etc. So I needed to import the self-signed cert into the Alfresco JRE. If we do not do this then we will keep getting the following errors and no luck logging into Alfresco Share:

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

To import the cert do as follows:

  1. Export it from the keystore we generated for Tomcat

C:\>keytool -export -rfc -alias tomcat -file tomcat.crt –keystore c:/Users/mbergljung/.keystore -storepass changeit

Certificate stored in file <tomcat.crt>

  1. Then import it into the Alfresco JRE certificate store:

C:\>keytool -import -alias tomcat -file tomcat.crt -keystore X:/Alfresco3.4EWWARN/java/jre/lib/security/cacerts -storepass changeit

Owner: CN=localhost, OU=Dev, O=Ixxus, L=London, ST=London, C=UK

Issuer: CN=localhost, OU=Dev, O=Ixxus, L=London, ST=London, C=UK

Serial number: 4df48ecd

Valid from: Sun Jun 12 11:02:53 BST 2011 until: Sat Sep 10 11:02:53 BST 2011

Certificate fingerprints:

         MD5:  F1:69:DA:CE:0D:F7:D3:9F:9F:9C:12:9B:8B:54:3F:B8

         SHA1: 82:7A:0D:83:DC:99:07:4E:3A:98:95:13:52:EB:B1:20:EB:C9:89:4B

         Signature algorithm name: SHA1withRSA

         Version: 3

Trust this certificate? [no]:  yes

Certificate was added to keystore

Note. In a deployment where the CA server runs on one Tomcat instance on one host, and the Alfresco server runs on one Tomcat instance on another host, you would need to import the Alfresco Tomcat self-signed cert into the JRE that runs CAS.

Note 2. In a production scenario you would not need to worry about this as you would have properly signed certificates from a Certificate Authority (CA), and these will be automatically recognized as trusted by the JRE you are using.

Installing CAS in the same Tomcat instance as Alfresco

We will use a local CAS running in the same Tomcat instance as Alfresco to test the complete configuration. Download CAS version 3.4.x from http://www.jasig.org/cas and unzip in some folder. Then grab the .../cas-server-3.4.6/modules/cas-server-webapp-3.4.6.war web application and drop it into the alfresco/tomcat/webapps directory.

This is the only thing we need to do to start using CAS as it provides a testing mode out of the box where you can just supply the same username and password for a successful authentication.

To test CAS go to https://localhost:8443/cas-server-webapp-3.4.6/login and test logging in with the same username and password. You will also test your SSL configuration at the same time.

Logout afterwards with https://localhost:8443/cas-server-webapp-3.4.6/logout 

Configuring CAS SSO for Alfresco Explorer

To setup SSO for Alfresco Explorer with CAS I will use the files/code available from the following link:

 http://akselsarchitecture.blogspot.com/2010/09/cas-sso-for-alfresco-33-and-share.html 

I have modified these files a bit as they have hard coded URLs. You can get all my files from my download page; a link to it is available at the right side of the blog page.

The following steps are needed to configure SSO for Alfresco Explorer:

  1. Enable external authentication for Alfresco Explorer/Repo (this turns off the standard alfrescoNtlm1 authenticator). Open up the alfresco/tomcat/shared/classes/alfresco-global.properties file and add the following lines:

### Enable CAS SSO Authentication via EXTERNAL subsystem

authentication.chain=cas:external

Note. This does not turn on any extra CAS SSO authentication functionality or anything; we are just telling Alfresco that authentication will be handled via an external authentication mechanism and Alfresco should not worry about it.

  1. Update the tomcat/webapps/alfresco/WEB-INF/web.xml file with some new filters that will talk to the CAS server and comment out Alfresco’s default authentication filter (an example web.xml can be found in the alfresco_war\WEB-INF directory of the source code package for this blog):

<!-- Commented out Alfresco's default authentication filter in order to be able to configure CAS filters

   <filter>

      <filter-name>Authentication Filter</filter-name>

      <description>Authentication filter mapped only to faces URLs. Other URLs generally use proprietary means to talk to the AuthenticationComponent</description>

      <filter-class>org.alfresco.repo.web.filter.beans.BeanProxyFilter</filter-class>

      <init-param>

         <param-name>beanName</param-name>

         <param-value>AuthenticationFilter</param-value>

      </init-param>

   </filter>

   -->

<!-- Adding CAS Authentication filters and replacing Alfresco's default one -->

   <filter>

      <filter-name>Authentication Filter</filter-name>

      <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>

      <init-param>

         <param-name>casServerLoginUrl</param-name>

         <param-value>https://localhost:8443/cas-server-webapp-3.4.6/login</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</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://localhost:8443/cas-server-webapp-3.4.6</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</param-value>

      </init-param>

   </filter>

   <filter>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <filter-class>org.mycompany.cms.authentication.CasAuthenticationFilter</filter-class>

   </filter>

   <!-- End adding CAS authentication filters -->

The first two filters are provided by the CAS client library and the third one we have to make some changes to and provide in a library. Notice that the CAS server is accessed via a secure connection (https) but the Alfresco Explorer application is accessed via a plane connection (http).

Now configure the filter mappings as follows:

<!-- New CAS filter mappings starts here -->

   <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/faces/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/faces/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/navigate/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/navigate/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/navigate/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/command/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/command/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/command/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/download/*</url-pattern>

   </filter-mapping>

      <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/download/*</url-pattern>

   </filter-mapping>

      <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/download/*</url-pattern>

   </filter-mapping>

   

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/template/*</url-pattern>

   </filter-mapping>

      <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/template/*</url-pattern>

   </filter-mapping>

      <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/template/*</url-pattern>

   </filter-mapping>

   

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/n/*</url-pattern>

   </filter-mapping>

      <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/n/*</url-pattern>

   </filter-mapping>

      <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/n/*</url-pattern>

   </filter-mapping>

   

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/c/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/c/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/c/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/t/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/t/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/t/*</url-pattern>

   </filter-mapping>

   

   <filter-mapping>

      <filter-name>Authentication Filter</filter-name>

      <url-pattern>/d/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/d/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/d/*</url-pattern>

   </filter-mapping>

        <!-- New CAS filter mappings end here -->

  1. Make sure the URLs in the org.mycompany.cms.authentication.LoginCas Web Script controller class are correct:

public class LoginCas extends DeclarativeWebScript {

    private final static String CAS_WEBAPP_URL = "https://localhost:8443/cas-server-webapp-3.4.6";

    private final static String ALFRESCO_WEBAPP_URL = "http://localhost:8080/alfresco";

  1. Configure the LoginCas web script controller in a Spring context file:

The declarative web script needs to be loaded and setup from a Spring bean configuration. If you are creating a new AMP file for this then add the following Spring bean configuration to the module-context.xml:

<bean id="webscript.org.mycompany.authentication.logincas.get" class="org.mycompany.cms.authentication.LoginCas" parent="webscript">

                <property name="authenticationService" ref="authenticationService" />

                <property name="authenticationComponent" ref="authenticationComponent" />

        </bean>

  1. Lookup how to setup an AMP build project and use it to package together the web script controller, authentication filter, CAS library, and Spring context file

The following two classes from the alfresco_war package source code need to be compiled against the Alfresco 3.4 SDK and CAS library:

org.mycompany.cms.authentication.LoginCas

org.mycompany.cms.authentication.CasAuthenticationFilter

To compile these classes you need the CAS Client library (e.g. cas-client-core-3.1.12.jar), and it need to be packaged in the AMP as well.

  1. Stop Tomcat if it is running, and delete alfresco/tomcat/webapps/alfresco

  1. Now apply the Alfresco WAR extension AMP to the alfresco/tomcat/webapps/alfresco.war 

  1. Start Tomcat, and wait for the alfresco.war to be deployed, then stop Tomcat

  1. Copy the modified web.xml to /alfresco/tomcat/webapps/alfresco/WEB-INF directory (the web.xml cannot be updated via AMP files)

  1. Start Tomcat

  1. Now test the SSO integration by going to http://localhost:8080/alfresco, this should take you to the CAS login page

  1. If you hit logout in Alfresco Explorer it will not log you out from CAS, you can fix this by updating the alfresco/tomcat/webapps/alfresco/jsp/org/relogin.jsp (this can be included in the AMP as well) and adding a redirect as follows:

. . .

authCookie.setMaxAge(0);

response.addCookie(authCookie);

}

}

// Logout from CAS

response.sendRedirect("http https://localhost:8443/cas-server-webapp-3.4.6/logout");

%>

<body bgcolor=

Configuring CAS SSO for Alfresco Share

For this I also use files/code available from the following link:

 http://akselsarchitecture.blogspot.com/2010/09/cas-sso-for-alfresco-33-and-share.html 

I have modified these files a bit as they have hard coded URLs and I also added a more descriptive error message in one place. You can get all my files from my download page; a link to it is available at the right side of the blog page.

The following steps are needed to configure SSO for Alfresco Share:

  1. Update the tomcat/webapps/share/WEB-INF/web.xml file with some new filters that will talk to the CAS server and comment out Alfresco’s default authentication filter (an example web.xml can be found in the share_war\WEB-INF directory of the source code package for this blog):

<!-- Adding CAS Authentication filters -->

   <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://localhost:8443/cas-server-webapp-3.4.6/login</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</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://localhost:8443/cas-server-webapp-3.4.6</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</param-value>

      </init-param>

      <init-param>

         <param-name>allowAnyProxy</param-name>

         <param-value>true</param-value>

      </init-param>

      <init-param>

         <param-name>proxyCallbackUrl</param-name>

         <param-value>https://localhost:8443/share/proxyCallback</param-value>

      </init-param>

      <init-param>

         <param-name>proxyReceptorUrl</param-name>

         <param-value>/proxyCallback</param-value>

      </init-param>

   </filter>

   <filter>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <filter-class>org.mycompany.cms.authentication.CasAuthenticationFilter</filter-class>

   </filter>

<!-- End adding CAS authentication filters -->

The first two filters are provided by the CAS client library and the third one we have to make some changes to and provide in a library. Notice that the CAS server is accessed via a secure connection (https) but the Alfresco Share application is accessed via a plane connection (http). There is one exception though; the proxyCallbackUrl callback URL requires a secure connection to Alfresco. (One thing to note, if you access Alfresco Share via https the Multi File upload Flash component might not work).

Now configure the filter mappings as follows:

<!-- Adding CAS Authentication filter mappings -->

        <filter-mapping>

      <filter-name>CAS Validation Filter</filter-name>

      <url-pattern>/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>CAS Authentication Filter</filter-name>

      <url-pattern>/*</url-pattern>

   </filter-mapping>

   <filter-mapping>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <url-pattern>/*</url-pattern>

   </filter-mapping>

   <!-- End adding CAS Authentication filter mappings -->        

  1. Make sure the URL in the org.mycompany.cms.authentication.CasAuthenticationFilter class are correct:

public class CasAuthenticationFilter implements Filter {

    private final static String ALFRESCO_WEBAPP_URL = "http://localhost:8080/alfresco";

  1. Update the share-config-custom.xml with the new authenticator to use, the one that will call the LoginCas Web Script with a CAS ticket:

  <!--Overriding endpoints to reference a remote Alfresco server &ndash;&gt;-->

    <config evaluator="string-compare" condition="Remote">

        <remote>

            <!-- Authenticator implementation used in CAS authentication scenario,

                overrides the default alfresco-ticket authenticator

                <class>org.alfresco.connector.AlfrescoAuthenticator</class> -->

            <authenticator>

                <id>alfresco-ticket</id>

                <name>Alfresco Authenticator</name>

                <description>Alfresco Authenticator</description>

                <class>org.mycompany.cms.authentication.CasAlfrescoAuthenticator

</class>

            </authenticator>

            <!-- Connects to an Alfresco instance using ticket-based authentication,

                overrides the default alfresco connector to use CAS ticket

authenticator-->

            <connector>

                <id>alfresco</id>

                <name>Alfresco Connector</name>

                <description>Connects to an Alfresco instance using ticket-based

authentication</description>

                <class> org.springframework.extensions.webscripts.connector.AlfrescoConnector

</class>

                <authenticator-id>alfresco-ticket</authenticator-id>

            </connector>

            <!-- Endpoint using external authentication via CAS-->

            <endpoint>

                <id>alfresco</id>

                <name>Alfresco - user access</name>

                <description>Access to Alfresco Repository WebScripts that require

external user authentication

                </description>

                <connector-id>alfresco</connector-id>

                <endpoint-url>http://localhost:8080/alfresco/s</endpoint-url>

                <identity>user</identity>

                <external-auth>true</external-auth>

            </endpoint>

        </remote>

    </config>

  1. Lookup how to setup a JAR extension project for Alfresco Share and use it to package together the authentication filter, authenticator, and share-config-custom.xml

The following two classes from the share_war package source code need to be compiled against the Alfresco 3.4 SDK and CAS library:

org.mycompany.cms.authentication.CasAlfrescoAuthenticator

org.mycompany.cms.authentication.CasAuthenticationFilter

To compile these classes you need the CAS Client library (e.g. cas-client-core-3.1.12.jar).

  1. Stop Tomcat if it is running

  1. Copy the Share extension JAR plus the CAS library JAR into the alfresco/tomcat/webapps/share/WEB-INF/lib directory

  1. Copy the modified web.xml to /alfresco/tomcat/webapps/share/WEB-INF directory

  1. Start Tomcat

  1. Now test the SSO integration by going to http://localhost:8080/share, this should take you to the CAS login page, unless you already have a session from login into Alfresco Explorer, then you should be automatically logged in

Putting the CAS server on a separate host

Deploying the CAS web application and the Alfresco web applications into the same Apache Tomcat server simplifies the configuration quite a lot. It is not a simple task to move the CAS server to a separate host. Deploying the CAS server on its own Apache Tomcat server will require some more re-configuration and more network related issues to think about.

I am assuming you have followed the article so far and have now got the solution working with everything installed in the Alfresco Tomcat server, with a "localhost" certificate for Tomcat.

The following is a picture of the configuration I am setting up to demonstrate having CAS on a separate host:

In this scenario CAS is not backed by a user directory. The authentication is done via the default CAS test mode where you can just use the same username and password to achieve a successful login.

Both of the Apache Tomcat servers have a keystore with a self-signed certificate. These certificates are also imported into the Java environments that are used to run the Tomcat servers. The CAS host is not connected to a domain so the hosts file contains an entry for the Alfresco host (i.e. IXDV1210). The Alfresco host also contains an entry in the hosts file for the CAS host (i.e. cashost).

It is important that the 8443 port is open in the Windows Firewall for this to work and this can easily be tested via a web browser call from each host when the Tomcat servers have been configured for secure access.

Setting up the new CAS server

This section goes through how to setup the CAS server on a separate host.

Installing CAS on a separate host

I am using a second laptop running Windows Vista for the CAS server. I have installed Apache Tomcat version 5.5 and copied the cas-server-webapp-3.4.6.war file into the /webapps directory. The Tomcat server configuration looks like this (from /conf/server.xml), se previous configuration information in this article for more information:

<Server port="8005" shutdown="SHUTDOWN">

  <!-- <Listener className="org.apache.catalina.core.AprLifecycleListener" />-->

  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />

  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

  <Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>

  . . .

  <Service name="Catalina">

    <Connector port="8080" address="0.0.0.0" maxHttpHeaderSize="8192"

               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"

               enableLookups="false" redirectPort="8443" acceptCount="100"

               connectionTimeout="20000" disableUploadTimeout="true" />

    <Connector port="8443" address="0.0.0.0" maxHttpHeaderSize="8192"

               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"

               enableLookups="false" disableUploadTimeout="true"

               acceptCount="100" scheme="https" secure="true"

               clientAuth="false" sslProtocol="TLS"

                keystoreFile="C:/Users/martin/.keystore" keystorePass="changeit"/>

   

  . . .

One thing is different here from the Tomcat 6.0 configuration mentioned previously in this article. The address="0.0.0.0" need to be specified otherwise Tomcat 5.5 will not bind to all interfaces and we will not be able to access the server remotely.

Generating a self-signed certificate for the Tomcat server that runs CAS

As the CAS server is accessed securely (which is mandatory) we need to create the keystore we are referencing in the server.xml file configuration above, and add a certificate to it. The certificate needs to have the alias and CN properties set to the hostname of the CAS server. The Vista laptop that I am using is not hooked up to a domain so I am just going to generate the certificate with a hostname of cashost (the Alfresco Tomcat server will use cashost to access CAS). I used the following command to generate the self-signed certificate and keystore in my user home directory:

C:\>keytool -genkey -alias cashost -keyalg RSA

Enter keystore password:

Re-enter new password:

What is your first and last name?

[Unknown]: cashost

What is the name of your organizational unit?

[Unknown]: Dev

What is the name of your organization?

[Unknown]: Ixxus

What is the name of your City or Locality?

[Unknown]: London

What is the name of your State or Province?

[Unknown]: London

What is the two-letter country code for this unit?

[Unknown]: UK

Is CN=cashost, OU=Dev, O=Ixxus, L=London, ST=London, C=UK correct?

[no]: Yes

Enter key password for <tomcat>

(RETURN if same as keystore password):

Testing the CAS installation

Before moving on we can test the CAS installation and make sure it works as expected.

Access the CAS application as follows:

https://localhost:8443/cas-server-webapp-3.4.6/login

We should get a login prompt where we can use same username and password to test logging in. We will not access via cashost (it will not work...), that hostname will only be used from the Alfresco server.

Letting the CAS host know about the Alfresco host

The CAS server will call back to the Alfresco Share web application as part of the proxy authentication scenario. This call needs to be secured and the Tomcat instance that runs Alfresco will have a new certificate generated with alias and CN set to IXDV1210.ixxus.co.uk. This hostname and domain is however not known by the Windows Vista laptop running Tomcat and the CAS web application, so we need to add it to the C:\Windows\System32\drivers\etc\hosts file as follows:

192.168.0.2     IXDV1210.ixxus.co.uk

Note. If both your hosts are connected to a domain then this step is not needed.

Updating the Alfresco installation and removing the CAS server

This section goes through how to update the Alfresco configuration to point to the new CAS server and how to remove currently installed CAS server.

Now stop Alfresco Tomcat if it is running!

Letting the Alfresco host know about the CAS host

The Alfresco server will call the CAS server via the cashost hostname. This is not a hostname that is known to the Alfresco host so we need to update the hosts file with an IP for that hostname. Open up the C:\Windows\System32\drivers\etc\hosts file and add the following line:

192.168.0.10     cashost

Note. If both your hosts are connected to a domain then this step is not needed.

Remove CAS from the Tomcat server that runs Alfresco

As we are running CAS from a separate host now we can remove it from the Alfresco Tomcat webapps directory. Remove both the c:\Alfresco3.4\tomcat\webapps\cas-server-webapp-3.4.6.war file and the c:\Alfresco3.4\tomcat\webapps\cas-server-webapp-3.4.6 directory.

Make sure the Alfresco host can get through to the CAS host on port 8443

The Alfresco host and the CAS host needs to have port 8443 open in their firewalls, otherwise it will not work. A quick way to test if it works is to use the browser on each host and try and access the other host on port 8443.

If it is not working open up "Allow program through Windows Firewall -> Windows Firewall settings" and in the Exceptions tab click the Add port... button to let through traffic on port 8443.

Updating the Login CAS Web Script

The login CAS web script has the URL for the CAS server hard coded so we need to update it as follows:

public class LoginCas extends DeclarativeWebScript {

    private final static String CAS_WEBAPP_URL =

"https://cashost:8443/cas-server-webapp-3.4.6";

And then we need to rebuild the Alfresco Explorer extension AMP by running the deploy-alfresco-amp ant target. Then start Alfresco and stop it again so the alfresco.war is deployed, we will be updating the web.xml for it in the next step.

Updating the web.xml for the Alfresco Explorer and the Alfresco Share web applications

The CAS web application is now running on a separate host so we need to update the web.xml files for the Alfresco Explorer and the Alfresco Share web applications, so that the URLs point to the new CAS host (web.xml cannot be updated via the build project as neither AMP or JAR extensions can update this file, you would need a Maven project for that). First open up the tomcat/webapps/alfresco/WEB-INF/web.xml file and update it so the following section looks like this:

<filter>

      <filter-name>Authentication Filter</filter-name>

 <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>

      <init-param>

         <param-name>casServerLoginUrl</param-name>

         <param-value>https://cashost:8443/cas-server-webapp-3.4.6/login</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</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://cashost:8443/cas-server-webapp-3.4.6</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</param-value>

      </init-param>

   </filter>

   <filter>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

      <filter-class>org.wwarn.cms.authentication.CasAuthenticationFilter</filter-class>

   </filter>

Note that the hostname for the CAS server is specified as cashost, which is resolved via the hosts file configuration. As mentioned before the CAS server requests need to be secure (i.e. https).

Now, the Alfresco Share web.xml also needs to be updated, it’s located in the tomcat/webapps/share/WEB-INF directory and needs to be updated so the following section looks like this:

<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://cashost:8443/cas-server-webapp-3.4.6/login</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</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://cashost:8443/cas-server-webapp-3.4.6</param-value>

      </init-param>

      <init-param>

         <param-name>serverName</param-name>

         <param-value>http://localhost:8080</param-value>

      </init-param>

      <init-param>

         <param-name>allowAnyProxy</param-name>

         <param-value>true</param-value>

      </init-param>

      <init-param>

         <param-name>proxyCallbackUrl</param-name>

      <param-value>https://IXDV1210.ixxus.co.uk:8443/share/proxyCallback</param-value>

      </init-param>

      <init-param>

         <param-name>proxyReceptorUrl</param-name>

         <param-value>/proxyCallback</param-value>

      </init-param>

   </filter>

   <filter>

      <filter-name>Alfresco CAS Authentication Filter</filter-name>

   <filter-class>org.wwarn.cms.authentication.CasAuthenticationFilter</filter-class>

   </filter>

Here we can see also that all URLs need to be secure for the proxy authentication scenario to work. Note the proxyCallbackUrl that is used by CAS to call back to the service (i.e. Alfresco) during a proxy authentication scenario.

Generating a new self-signed certificate for the Tomcat server that runs Alfresco

The Apache Tomcat that currently runs the Alfresco web applications and the CAS web application needs to have a new certificate generated as it currently has "localhost" as alias and CN, which would not work when it is access remotely (via the https://.../share/proxyCallback request made by the CAS server).

The laptop that I am running Alfresco Tomcat on has a hostname of IXDV1210 and is part of the ixxus.co.uk domain. So I generated the new self-signed certificate in the Tomcat keystore as follows:

C:\>keytool -genkey -alias IXDV1210.ixxus.co.uk -keyalg RSA

Enter keystore password:

Re-enter new password:

What is your first and last name?

[Unknown]: IXDV1210.ixxus.co.uk

What is the name of your organizational unit?

[Unknown]: Dev

What is the name of your organization?

[Unknown]: Ixxus

What is the name of your City or Locality?

[Unknown]: London

What is the name of your State or Province?

[Unknown]: London

What is the two-letter country code for this unit?

[Unknown]: UK

Is CN=IXDV1210.ixxus.co.uk, OU=Dev, O=Ixxus, L=London, ST=London, C=UK correct?

[no]: Yes

Enter key password for <tomcat>

(RETURN if same as keystore password):

I then also removed the old “localhost” certificate so it is not picked up by mistake by Tomcat:

C:\Alfresco3.4\java\bin>keytool -delete -alias tomcat -keystore C:/Users/mbergljung/.keystore -storepass changeit

Importing the CAS Host certificate into the Alfresco Host Java runtime environment

For the Alfresco secure calls to the CAS server to work we need to import the CAS host certificate into the Java runtime environment that runs the Tomcat with the Alfresco server. This was done as follows; first export the certificate from the keystore that Tomcat uses on the CAS Host:

C:\Program Files\Java\jdk1.6.0_14\bin>keytool -export -rfc -alias cashost -file c:/Users/martin/cashost.crt -keystore c:/Users/martin/.keystore -storepass changeit

Certificate stored in file <c:/Users/martin/cashost.crt>

Then import it into the Java runtime environment on the Alfresco host (you need to first copy the certificate file to the Alfresco host):

X:\Alfresco3.4\java\bin>keytool -import -alias cashost -file Z:/temp/cashost.crt -keystore X:/Alfresco3.4/java/jre/lib/security/cacerts -storepass changeit

The CAS host is now trusted by the Java environment running the Alfresco server.

Note. if you have a properly CA signed certificate then this import step is not needed as the Java runtime environment will have a trust chain already setup to verify the certificate.

Importing the Alfresco Host certificate into the CAS Host Java runtime environment

For the CAS secure callback to Alfresco to work we need to import the Alfresco host certificate into the Java runtime environment that runs the Tomcat with the CAS server. This was done as follows; first export the certificate from the keystore that Tomcat uses on the Alfresco Host:

X:\Alfresco3.4\java\bin>keytool -export -rfc -alias IXDV1210.ixxus.co.uk -file alfrescohost.crt -keystore c:/Users/mbergljung/.keystore -storepass changeit

Certificate stored in file <alfrescohost.crt>

Then import it into the Java runtime environment on the CAS host (you need to first copy the certificate file to the CAS host):

C:\>keytool -import -alias IXDV1210.ixxus.co.uk -file z:/temp/alfrescohost.crt -keystore "C:/Program Files/Java/jdk1.6.0_14/jre/lib/security/cacerts" -storepass changeit

The Alfresco host is now trusted by the Java environment running the CAS server.

Note. if you have a properly CA signed certificate then this import step is not needed as the Java runtime environment will have a trust chain already setup to verify the certificate.