Skip to main content

In our ongoing effort to show how easy it is to add two-factor authentication to various services, we have integrated the open-source single sign-on tool CAS with WiKID for two-factor authentication. The CAS server is running on Ubuntu 11.04 Server and is using Radius to talk to the WiKID Strong Authentication Server Enterprise Edition.

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 one-time passwords 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.

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="authenticationHandlerskid10.jpeg
CAS_wikid09.jpegCAS_wikid09.jpeg">
			<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>

 

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>

 

You can now build the war file using Maven:

mvn clean package

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 the correct:

<bean class="net.jradius.client.auth.PAPAuthenticator" />

Configurating Tomcat

Star by downloading the latest tomcat and untar it. At the time of this writing that was 7.0.22.

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" />

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

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.

CAS_wikid01.jpeg

Click Add or Modify and enter the shared secret. Make sure that the shared secret is the same as in the deployerContext.xml file.

CAS_wikid02.jpeg

Now let's add mutual https authentication to the mix. 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:

CAS_wikid03.jpeg

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

User registration and logging In

Registering the token

Start your WiKID software token. Select Action, Create new domain. Enter the 12 digit domain identifier for your WiKID server. This is typically the zero-padded IP address.

CAS_wikid08.jpeg

You will be prompted to set a PIN.

CAS_wikid09.jpeg

You will get back a registration code from the server. This registration must be validated for the user to login.

CAS_wikid10.jpeg

Log in to the WiKIDAdmin and click on the Users tab and then Manually validate a user. You will see your registration code.

CAS_wikid11.jpeg

Click on the registration code and enter your username on the following page.

Now, head back to the token to the and select Get Passcode.

CAS_wikid04.jpeg

Enter your PIN.

CAS_wikid05.jpeg

You will get back an OTP from the WiKID Strong Authentication Server. Additionally, your default browser will be opened the CAS login page as specified under the Registered URL.

CAS_wikid06.jpeg

 

Now Login to the CAS SSO page with your username and WiKID one-time passcode.

CAS_wikid07.jpeg

CAS SSO with two-factor authentication

If you run the PC software token in debug mode, you will see the token validating the SSL certificate for you:

Received 128 bytes from server.
validatedURL() processing response ...
validatedURL() returned url: https://cas.wikidsystems.com/cas/login
validatedURL() hash_from_server: 14Bqov7lBEMn+DavECDMovCBTF0=
validatedURL() hash_from_me: 14Bqov7lBEMn+DavECDMovCBTF0=
validatedURL() validated_url: https://cas.wikidsystems.com/cas/login
Validity check returning: https://cas.wikidsystems.com/cas/login

 

If there is a Man-in-the-Middle attack the user will get an error that the URL has changed. The debug output will show that the hashes do not match:

Received 128 bytes from server.
validatedURL() processing response ...
validatedURL() hash_from_server: 14Bqov7lBEMn+DavECDMovCBTF0=
validatedURL() hash_from_me: /HAtxIVzVL6yo1OjTkPca74xd8s=
Validity check returning: null

 

Conclusion

Single sign-in is a great tool but it creates a "keys to the kingdom" situation where compromising a single set of credentials can result in a much larger breach than without SSO. Additionally, organizations are using SSO for cloud-based services such as Google Apps.



 

Copyright © WiKID Systems, Inc. 2024 | Two-factor Authentication