Addon that helps to integrate WWPass authentication into Jasig CAS Single Sign-On Server
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
cas-server-support-wwpass
cas_example
.gitignore
LICENSE
README.md

README.md

cas-server-support-wwpass

This module allows you to integrate WWPass Authentication into JASIG CAS Single Sign-On Server.

NOTE: The distribution consists of two parts - the support module itself and an example application. For the example app to operate properly we bring specific CAS configuration based on MySQL user data tables. Due to CAS architecture and source-based nature some MySQL modules should be compiled in when creating CAS.war file.

Installation & Configuration

Create a WWPass Developer Account

Signup for a free account on WWPass developers website and follow the getting started instructions to obtain WWPass authorization credentials (WWPass certificate file and a private key file) for your CAS server: .

Build the server extension

cd cas-server-support-wwpass
mvn clean package install

Use the Maven Overlay Method to configure CAS

Follow the instructions in http://jasig.github.io/cas/4.0.0/installation/Maven-Overlay-Installation.html and download the template https://github.com/UniconLabs/simple-cas4-overlay-template

Quick configuration

CAS server behaviour depends on a set of configuration files - compilation-time and run-time

cas-server-support-wwpass distribution comes with a ready-made set of files, which produce demo CAS server working with our example app.

You will find the files in cas-server-support-wwpass/overlay-extra directory.

Copying instructions:

#!/bin/sh

CFG_SRC="cas-server-support-wwpass/overlay-extra"
CFG_DEST="simple-cas4-overlay-template-master"

cp $CFG_SRC/resources/default_views.properties $CFG_DEST/src/main/resources/
cp $CFG_SRC/webapp/WEB-INF/view/jsp/default/ui/wwpassCasLoginView.jsp $CFG_DEST/src/main/webapp/WEB-INF/view/jsp/default/ui/
cp $CFG_SRC/webapp/WEB-INF/login-webflow.xml $CFG_DEST/src/main/webapp/WEB-INF/
cp $CFG_SRC/webapp/WEB-INF/deployerConfigContext.xml $CFG_DEST/src/main/webapp/WEB-INF/

cp -r $CFG_SRC/webapp/css $CFG_DEST/src/main/webapp/
cp -r $CFG_SRC/webapp/images $CFG_DEST/src/main/webapp/

cp $CFG_SRC/pom.xml $CFG_DEST/

cp $CFG_SRC/cas.properties /etc/cas/

# NOTE: next file comes from simple-cas4-overlay-template:

cp $CFG_DEST/etc/log4j.xml /etc/cas/

Edit WWPass settings in /etc/cas/cas.properties - registered SP name and paths to certificate and private key files:

# WWPass Settings
wwpass.certPath=/etc/ssl/certs/your_site.crt
wwpass.keyPath=/etc/ssl/certs/your_site.key

wwpass.sp.name=your_site_name

Now use cas-server-support-wwpass/overlay-extra/sample-schema.sql file to create the example user MySQL database

Finally compile CAS.war:

cd simple-cas4-overlay-template-master
mvn clean package install

You are done

Compiling Example CAS client

Goto cas-example directory provided with cas-server-support-wwpass and compile it as usually

cd cas-example
mvn clean package install

The directory has its own Readme.md file with instructions.

The example app shares the MySQL user database with CAS server. Use cas-server-support-wwpass/overlay-extra/sample-schema.sql file to create the database.

Configuration details

NOTE: some parts of configuration files correspond to particular MySQL-based example. You will rather use your own user catalog. This MySQL configuration is just easy-to-understand example.

pom.xml

Add the following block to the pom.xml in CAS overlay directory:

    <dependency>
      <groupId>com.wwpass</groupId>
      <artifactId>cas-server-support-wwpass</artifactId>
      <version>0.1</version>
    </dependency>

Modify build section as follows:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <warName>cas</warName>
                    <overlays>
                        <overlay>
                            <groupId>org.jasig.cas</groupId>
                            <artifactId>cas-server-webapp</artifactId>
                            <excludes>
                                <exclude>WEB-INF/cas.properties</exclude>
                                <exclude>WEB-INF/classes/log4j.xml</exclude>
                                <exclude>WEB-INF/deployerConfigContext.xml</exclude>
                                <exclude>WEB-INF/login-webflow.xml</exclude>
                                <exclude>WEB-INF/classes/default_views.properties</exclude>
                            </excludes>
                        </overlay>
                    </overlays>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
        <finalName>cas</finalName>
    </build>

deployerConfigContext.xml

First, copy deployerConfigContext.xml from cas-server-support-wwpass/overlay-extra to _cas_overlay_folder_/src/main/webapp/WEB-INF/. Also you can use default deployerConfigContext.xml file, for example, from CAS distribution (cas-server-webapp/src/main/webapp/WEB-INF/deployerConfigContext.xml). After you copy it to you overlay, follow the instructions bellow:

  • add the WwpassAuthenticationHandler bean to the list of authentication handlers in deployerConfigContext.xml:
    <bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
    
        <constructor-arg>
            <map>
                <entry key-ref="dbAuthHandler" value-ref="usernamePasswordCredentialsResolver"/>
                <entry key-ref="wwpassAuthenticationHandler" >
                    <null/>
                </entry>
            </map>
        </constructor-arg>
        
        <property name="authenticationPolicy">
            <bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy"/>
        </property>
    </bean>
    <bean id="wwpassAuthenticationHandler"
          class="com.wwpass.cas.support.authentication.handler.WwpassAuthenticationHandler">
        <property name="wwpassConnection" ref="wwpassConnection"/>
        <property name="wwpassDAO" ref="jdbcWwpassDAO"/>
    </bean>

    <bean name="wwpassConnection" class="com.wwpass.connection.WWPassConnection">
        <constructor-arg name="certFile" value="${wwpass.certPath}"/>
        <constructor-arg name="keyFile" value="${wwpass.keyPath}"/>
    </bean>

    <bean id="jdbcWwpassDAO"
          class="com.wwpass.cas.support.dao.JdbcWwpassDao">
        <property name="dataSource" ref="dataSource"/>    
    </bean>
  • wwpassConnection = A bean represents library, which allows to authenticate user via WWPass.
  • jdbcWwpassDao - A JDBC-based user servise, which implements interface WwpassDAO. You can write your own implementation of this interface, for example, getting user's principal from LDAP by WWPass PUID (PUID - user/service_provider unique identifier).
  • if you decide to use JDBC-based user storage, you'll also need to add dataSource bean, for example, using c3p0 library:
    <bean id="dataSource"
          class="com.mchange.v2.c3p0.ComboPooledDataSource"
          p:driverClass="${database.driverClass}"
          p:jdbcUrl="${database.url}"
          p:user="${database.user}"
          p:password="${database.password}"
          p:initialPoolSize="${database.pool.minSize}"
          p:minPoolSize="${database.pool.minSize}"
          p:maxPoolSize="${database.pool.maxSize}"
          p:maxIdleTimeExcessConnections="${database.pool.maxIdleTime}"
          p:checkoutTimeout="${database.pool.maxWait}"
          p:acquireIncrement="${database.pool.acquireIncrement}"
          p:acquireRetryAttempts="${database.pool.acquireRetryAttempts}"
          p:acquireRetryDelay="${database.pool.acquireRetryDelay}"
          p:idleConnectionTestPeriod="${database.pool.idleConnectionTestPeriod}"
          p:preferredTestQuery="${database.pool.connectionHealthQuery}" />

then add c3p0 dependency to pom.xml in CAS overlay directory:

    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>

and JDBC driver dependency for database type you are using, for example, MySQL:

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>

By default JdbcWwpassDao uses SQL schema described in file cas-server-support-wwpass/overlay-extra/sample-schema.sql to get username by PUID, but you can change query by setting up the usernameByPuidQuery property.

/etc/cas/cas.properties

To keep confidential information out of the XML config files, the configuration data should be saved in cas.properties file:

Note, that by default this file must be on the path "/etc/cas/cas.properties", it is suitable for Linux systems. But if using Windows, you can change this setting in file "cas_overlay_directory/src/webapp/WEB-INF/spring-configuration/propertyFileConfigurer.xml"

# == WWPass Settings ==

# Your Service Provider's certificate and key paths
wwpass.certPath=/etc/ssl/certs/example.com.crt
wwpass.keyPath=/etc/ssl/certs/example.com.key

# Service Provider's name on which the certificate was issued
wwpass.sp.name=example.com


# == Basic database connection pool configuration ==
database.driverClass=com.mysql.jdbc.Driver
database.url=jdbc:mysql://127.0.0.1/wwpass_cas
database.user=cas
database.password=changeit
database.pool.minSize=6
database.pool.maxSize=18
 
# Maximum amount of time to wait in ms for a connection to become
# available when the pool is exhausted
database.pool.maxWait=10000
 
# Amount of time in seconds after which idle connections
# in excess of minimum size are pruned.
database.pool.maxIdleTime=120
 
# Number of connections to obtain on pool exhaustion condition.
# The maximum pool size is always respected when acquiring
# new connections.
database.pool.acquireIncrement=6
 
# == Connection testing settings ==
 
# Period in s at which a health query will be issued on idle
# connections to determine connection liveliness.
database.pool.idleConnectionTestPeriod=30
 
# Query executed periodically to test health
database.pool.connectionHealthQuery=select 1
 
# == Database recovery settings ==
 
# Number of times to retry acquiring a _new_ connection
# when an error is encountered during acquisition.
database.pool.acquireRetryAttempts=5
 
# Amount of time in ms to wait between successive aquire retry attempts.
database.pool.acquireRetryDelay=2000

default_views.properties

To authenticate with WWPass, you'll need to add one new view - wwpassCasLoginView.
Add the following lines to the end of properties file for your theme(s) or default_views.properties if you are using the default CAS theme.

### WWPass Login view
wwpassCasLoginView.(class)=org.springframework.web.servlet.view.JstlView
wwpassCasLoginView.url=/WEB-INF/view/jsp/default/ui/wwpassCasLoginView.jsp

login-webflow.xml

The final step is to modify the login webflow to display the WWPass login view instead of original CAS login view.

Simply replace viewLoginForm view-state:

    <view-state id="viewLoginForm" view="wwpassCasLoginView" model="wwpassExtentedCredentials">
        <binder>
            <binding property="ticket" />
            <binding property="username" />
            <binding property="password" />
        </binder>
        <on-entry>
            <set name="viewScope.commandName" value="'wwpassExtentedCredentials'" />
            <set name="viewScope.wwpassCommandName" value="'wwpassExtentedCredentials'" />
            <set name="viewScope.spName" value="'SDK%20Test'" />
        </on-entry>
        <transition on="submit" bind="true" validate="true" to="realSubmit">
            <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.wwpassExtentedCredentials)" />
        </transition>
    </view-state>
    

credential var replace with:

    <var name="wwpassExtentedCredentials" class="com.wwpass.cas.support.authentication.credential.WwpassWithUsernamePasswordCredentials" />

And realSubmit action-state replace with:

  <action-state id="realSubmit">
    <evaluate expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.wwpassExtentedCredentials, messageContext)" />
    <transition on="warn" to="warn" />
    <transition on="success" to="sendTicketGrantingTicket" />
    <transition on="successWithWarnings" to="showMessages" />
    <transition on="authenticationFailure" to="handleAuthenticationFailure" />
    <transition on="error" to="generateLoginTicket" />
  </action-state>