Configuring CAS On Ubuntu For Two-Factor Authentication With WiKID
Author: Nick Owen
Single sign-on is a great technology. Requiring users to login to multiple applications is huge hassle, encourages password reuse and simple passwords. Security needs to focus on usability. If you can make a user's life better while increasing security, everybody wins.
In this how-to we will set up the open-source CAS SSO product with the WiKID Strong Authentication Server for two-factor authentication for sessions and mutual https authentication for host authentication. Obviously using two-factor authentication for the login increases security because the user must have the factors to get access, in this case, knowledge of the PIN and possession of the private key embedded in the token. Less obvious is the benefit of strong mutual authentication. WiKID does this by downloading a hash of the CAS web site's SSL certificate with the one-time password. Before presenting the OTP, the token goes to the CAS URL via the user's connection, grabs the SSL cert and hashes it. If the hashes match, the OTP is presented and the default browser is launched to the CAS URL. If they do not match, then there is a potential attack and the user gets an error stating that the URL has changed. MiTM attacks are much easier to perform today thanks to the ubiquity of WiFi.
The CAS server is running on Ubuntu 11.04 Server and is using Radius to talk to the WiKID Strong Authentication Server Enterprise Edition.
Building CAS and the cas.war file
First, CAS is built with Maven, so you need to install it:
sudo apt-get install maven2
Next download the latest version of CAS from the site. The current release is 3.4.11.
wget http://downloads.jasig.org/cas/cas-server-3.4.11-release.tar.gz
untar cas-server-3.4.11-release.tar.gz
Edit pom.xml
cd cas-server-3.4.11/cas-server-webapp/
vim pom.xml
I added the following dependency to add support for radius:
<dependency> <groupId>${project.groupId}</groupId> <artifactId>cas-server-support-radius</artifactId> <version>${project.version}</version> </dependency>
Edit deployerContext.xml
vim src/main/webapp/WEB-INF/deployerConfigContext.xml
In this file, you want to comment out the SimpleTestUsernamePasswordAuthenticationHandler, which is for demo purposes and add in information on your radius configuration. These beans are listed under Authentication Handlers.
<property name="authenticationHandlers"> <list> <!-- | This is the authentication handler that authenticates services by means of callback via SSL, thereby validating | a server side SSL certificate. +--> <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient" /> <!-- | This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS | into production. The default SimpleTestUsernamePasswordAuthenticationHandler authenticates UsernamePasswordCredentials | where the username equals the password. You will need to replace this with an AuthenticationHandler that implements your | local authentication strategy. You might accomplish this by coding a new such handler and declaring | edu.someschool.its.cas.MySpecialHandler here, or you might use one of the handlers provided in the adaptors modules. +--> <!-- <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> --> <bean class="org.jasig.cas.adaptors.radius.authentication.handler.support.RadiusAuthenticationHandler"> <property name="servers"> <bean class="org.jasig.cas.adaptors.radius.JRadiusServerImpl"> <constructor-arg index="0" value="10.100.0.170" /> <constructor-arg index="1" value="secret" /> <constructor-arg index="2"> <bean class="net.jradius.client.auth.PAPAuthenticator" /> </constructor-arg> </bean> </property> </bean> </list> </property> </bean>
In this example, the CAS server is talking directly to the WiKID server. You might also have a radius server such as freeradius or NPS between CAS and WiKID doing authorization. If you have more than one of these, you can list the servers for redundancy:
<bean class="org.jasig.cas.adaptors.radius.authentication.handler.support.RadiusAuthenticationHandler"> <property name="servers"> <list> <bean class="org.jasig.cas.adaptors.radius.JRadiusServerImpl"> <constructor-arg index="0" value="10.100.0.170" /> <constructor-arg index="1" value="secret" /> <constructor-arg index="2"> <bean class="net.jradius.client.auth.PAPAuthenticator" /> </constructor-arg> </bean> <bean class="org.jasig.cas.adaptors.radius.JRadiusServerImpl"> <constructor-arg index="0" value="10.100.0.171" /> <constructor-arg index="1" value="secret" /> <constructor-arg index="2"> <bean class="net.jradius.client.auth.PAPAuthenticator" /> </constructor-arg> </bean> </list> </property> <property name="failoverOnException" value="true" /> </bean>
Note that the CAS documentation for radius has an error in it. If you get the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.jasig.cas.adaptors.radius.JRadiusServerImpl#1dd7736' defined in ServletContext resource [/WEB-INF/deployerConfigContext.xml]: Cannot create inner bean 'net.sf.jradius.client.auth.PAPAuthenticator#1c958af' of type [net.sf.jradius.client.auth.PAPAuthenticator] while setting constructor argument; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [net.sf.jradius.client.auth.PAPAuthenticator] for bean with name 'net.sf.jradius.client.auth.PAPAuthenticator#1c958af' defined in ServletContext resource [/WEB-INF/deployerConfigContext.xml]; nested exception is java.lang.ClassNotFoundException: net.sf.jradius.client.auth.PAPAuthenticator
This is due to using the outdated line "<bean class="net.sf.jradius.client.auth.PAPAuthenticator" />" rather than "<bean class="net.jradius.client.auth.PAPAuthenticator" />".
Configuring Tomcat
Start by downloading the latest tomcat and untar it. At the time of this writing that was 7.0.22. We will call this directory $tomcathome.
sudo tar -xzvf apache-tomcat-7.0.22.tar.gz
Create an SSL keystore:
keytool -genkey -alias tomcat -keyalg RSA
You will probably want to import a signed certificate for production, but this will do for testing.
Edit the $tomcathome/conf/server.xml file to create an SSL port.
sudo vim conf/server.xml
Create the listener:
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="/path/to/.keystore" keystorePass="keystorePassphrase" clientAuth="false" sslProtocol="TLS" /> <Connector port="443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="/path/to/.keystore" keystorePass="keystorePassphrase" clientAuth="false" sslProtocol="TLS" />
Start tomcat:
sudo $tomcathome/bin/startup.sh
If all is well, you should have a listener on port 8443:
sudo netstat -anp | grep 8443
tcp6 0 0 :::8443 :::* LISTEN 10105/java
Copying the war file into tomcat's webapps directory will deploy it:
cp /home/username/cas-server-3.4.11/cas-server-webapp/target/cas.war $tomcathome/webapps/
If you look in $tomcathome/logs/catalina.out, you should see this line: "INFO: Deploying web application archive cas.war".
Configuring WiKID
Adding a Radius Network Client
Complete instructions on setting up a WiKID server are available here. We will only cover the network client portion.
The CAS server will be a radius network client to the WiKID Strong Authentication Server. On the WiKIDAdmin web ui, got the the Network Clients tab and select "Create a new network client", then enter the information appropriate for your CAS server, selecting RADIUS as the protocol.
Click Add or Modify and enter the shared secret. Make sure that the shared secret is the same as in the deployerContext.xml file. Leave the Return Attributes empty.
Now let's add mutual https authentication to the mix. Note that currently, mutual https authentication only supports port 443 - the assumption is that this product is benefiting the average user who can't detect a MiTM attack or validate a certificate. Go to the domains tab on the WiKIDAdmin and edit or create the domain you intend to use. Under the Registered URL, the URL for your CAS server:
The WiKID server will go to that URL and store a hash of the SSL certificate. Please note:
Radius does a lot of caching, so you need to restart WiKID. If WiKID is controlling the firewall, this will also open a port to the CAS server. From the command line of the WiKID server run:
wikidctl restart