Table of Contents
Author: Martin Bergljung
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
Installing CAS on a separate host
Generating a self-signed certificate for the Tomcat server that runs CAS
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
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://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.
This section shows how to configure CAS support when the CAS server runs on the same Apache Tomcat as the Alfresco server.
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:
<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" />
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).
<!--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.
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:
C:\>keytool -export -rfc -alias tomcat -file tomcat.crt –keystore c:/Users/mbergljung/.keystore -storepass changeit
Certificate stored in file <tomcat.crt>
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.
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
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:
### 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.
<!-- 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 -->
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";
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>
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.
. . .
authCookie.setMaxAge(0);
response.addCookie(authCookie);
}
}
// Logout from CAS
response.sendRedirect("http https://localhost:8443/cas-server-webapp-3.4.6/logout");
%>
<body bgcolor=
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:
<!-- 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 -->
public class CasAuthenticationFilter implements Filter {
private final static String ALFRESCO_WEBAPP_URL = "http://localhost:8080/alfresco";
<!--Overriding endpoints to reference a remote Alfresco server –>-->
<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>
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).
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.
This section goes through how to setup the CAS server 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.
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):
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.
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.
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!
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.
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.
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.
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.
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.
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
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.
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.