Friday, September 20, 2013

SSO with CAS, Part 1: The Identity Provider



I recently had the opportunity to experiment with SSO using the CAS project (Central Authentication Service).  Unfortunately while the documentation and examples on the CAS website are sometimes helpful, they are also often lacking or out-of-date.  In this and subsequent posts, I'll relate my own experience setting up these servers.

For the purposes of these examples, I provisioned virtual machines on Amazon Web Services EC2 configured with Ubuntu 12, Tomcat 7, and Java 6.  In principle, the steps should not change much with a different OS or servlet container.  However, I assume in this post that you know how to install these things yourself on whatever platform you choose.

Also, CAS requires SSL.  For testing I did not want to purchase a real certificate, so I generated and installed self-signed certificates instead, which creates extra steps that you would not need in a production system.  Obviously if you may skip those steps if you have a real certificate.

1. Build the CAS war

In order to set up SSO we'll first need an Identity Provider (IdP).  In our case, a simple CAS server will do (latest as of this writing: 3.5.2).  The CAS war needs to be build manually, so we download the source and compile it ourselves (which requires Maven).

  mvn -Dmaven.test.skip=true package install  

This will generate a modules subdirectory where the cas-server-webapp.war is located.  Copy that file into the Tomcat webapps folder, and rename it to cas.war.

Note: there is also a cas-server-uber-webapp.war file, which packages all the CAS support jars into the war by default.  Either war will work, but I prefer a leaner webapp to start with, and then add modules as I need them, so I chose the former.

2. Create a self-signed certificate

As mentioned, CAS requires SSL.  So we need to generate a self-signed certificate to get started.  The JDK comes with a very handy tool called keytool that can help us.

  keytool -genkey -alias tomcat -keyalg RSA -keystore /usr/share/tomcat7/.keystore  

This generates a new key pair and adds it to the keystore in /usr/share/tomcat7, which is the home directory for the user tomcat.  The location of the keystore is important: by default, Tomcat will look for certificates in the home directory of the user it's running as.  On Ubuntu, Tomcat runs as the user tomcat, and so we put the keystore in its home directory (note: keytool will create the keystore if it doesn't exist).

As part of creating the keystore and the certificate, the keytool will ask for a password.  The default password used by Tomcat is "changeit" (all lower case), and I recommend following that convention even though it's possible to choose a different password.  Choosing a custom password can lead to some unexpected behavior unless you configure Tomcat correctly.

3. Turn SSL on in Tomcat

The final step to activating SSL is to tell Tomcat to use it.  This is as simple as opening Tomcat's conf/server.xml and uncommenting the appropriate line:

   <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"  
        maxThreads="150" scheme="https" secure="true"  
        clientAuth="false" sslProtocol="TLS"  
        />  

This assumes a lot of defaults.  There are many potential things to customize, and reviewing them is outside the scope of this blog post.  See the Tomcat SSL documentation if you need to do more than this.

4. (Optional) Fix CAS log location

The default logs directory for CAS is the local web directory, and this causes permission problems on Linux.  In order to work around it, we can modify the CAS webapp's log4j settings (located at /WEB-INF/classes/log4j.xml), and point cas.log and perfStats.log to a writable directory.

If you don't do this, you may see log write errors in the Tomcat logs, but CAS will still continue to function as expected.

5. Export CAS certificate

Because we're using a self-signed certificate, we need to export that cert and take it with us to any of the client Service Providers that will use SSO.  That certificate will need to be installed as a trusted source in the certificate chain on those boxes.  We'll get to that in a later post, but for now, export the certificate like so:

  keytool -export -alias tomcat -file cas.crt -keystore /usr/share/tomcat7/.keystore  

Hang on to this file for later.

6. Test it (cas.example.com)

The last thing we do is test our server by navigating a browser to the IdP main URL: https://cas.example.com:8443/cas.  We should be challenged with a login screen.

The default CAS server configuration uses an authentication scheme called SimpleTestUsernamePasswordAuthenticationHandler, which accepts and authenticates any user/password combination that is identical.  That is, admin/admin, jacksmith/jacksmith, etc. will all authenticate.  In the Tomcat logs, CAS warns us this authentication scheme ought never to be used in a production environment, but for now it's okay.  We'll cover user provisioning in a subsequent post.

Conclusion

We now have a fully functional IdP that can respond to CAS requests from any Service Provider (SP) trying to authenticate a user.  In my next post, we'll set up a very simple SP to do just this.