Using CAS2 PasswordHandlers in CAS3
This page documents the steps required to adapt your CAS 2 Password Handler to the CAS 3 AuthenticationHandler API, thereby using your CAS 2 PasswordHandler unchanged in CAS3. An alternative to using your CAS 2 PasswordHandler (or TrustHandler) in CAS 3 is to re-implement your authentication handler as a CAS 3 AuthenticationHandler.
Declarative configuration
In order to use a CAS 2 PasswordHandler in CAS 3, you'll need to edit three specific entries in the CAS 3 configuration files. You'll need to make two changes in the configuration of the web tier in order to make the web tier extract the needed information from the HttpServletRequests. Then you'll need to make one change in the configuration of the AuthenticationManager to declare your PasswordHandler on the receiving end of this information.
Declaring the Credential
Whereas CAS2 PasswordHandlers authenticated usernames and passwords in the context of their HttpServletRequest, CAS 3 introduces the abstraction of Credentials which come from but are not the HttpServletRequest. By default CAS3 uses UsernamePasswordCredentials, credentials that convey a username, password pair. This is insufficient to support as CAS2 PasswordHandler, because the CAS2 PasswordHandler API also exposes the HttpServletRequest. So, you'll need to override the default CAS3 credentials with LegacyCasCredentials. LegacyCasCredentials are like UsernamePasswordCredentials except they also convey the raw HttpServletRequest.
In CAS3, login is implemented as a flow. One of the actions in the flow is an instance of LogonFormAction, and it is this instance of LogonFormAction that you'll need to configure to use LegacyCasCredentials rather than its default of UsernamePasswordCredentials.
Step 1
Set the formObjectClass property of the LogonFormAction instance in cas-servlet.xml .
<bean id="loginFormAction" class="org.jasig.cas.web.flow.LoginFormAction"> <property name="centralAuthenticationService" ref="centralAuthenticationService" /> <!-- | we add this property definition, which instructs Spring to | call setFormObjectClass() on the LoginFormAction instance we're configuring, | configuring it to use LegacyCasCredentials as the form class. +--> <property name="formObjectClass" value="org.jasig.cas.adaptors.cas.LegacyCasCredentials" /> </bean>
Binding the Credential
Now that we've declared our LegacyCasCredentials, we need to introduce a Binder that will actually connect the HttpServletRequest to the Credentials. By default, CAS uses the Spring WebMVC binding that binds request parameters to JavaBean properties. This works great for populating the (default) UsernamePasswordCredentials username and password fields. We need to supplement this default binding with some binding that will set the HttpServletRequest into our LegacyCasCredentials. This binding also happens in LogonFormAction. So, we need to edit that same XML we just edited to also declare the LegacyCasCredentialsBinder.
Step 2
Set LegacyCasCredentialsBinder as the credentialsBinder property of the LogonFormAction instance in cas-servlet.xml .
<bean id="loginFormAction" class="org.jasig.cas.web.flow.LoginFormAction"> <property name="centralAuthenticationService" ref="centralAuthenticationService" /> <property name="formObjectClass" value="org.jasig.cas.adaptors.cas.LegacyCasCredentials" /> <!-- | Now we're setting the credentialsBinder JavaBean property of the LogonFormAction instance. | Here we're instructing Spring to call setCredentialsBinder() on the LogonFormAction instance, | feeding this property an instance of LegacyCasCredentialsBinder. |--> <property name="credentialsBinder"> <bean class="org.jasig.cas.adaptors.cas.LegacyCasCredentialsBinder"/> </property> </bean>
Adapting and declaring your PasswordHandler
Now we have CAS collecting and conveying all the authentication input you know and use from CAS2: the username, the password, and the raw HttpServletRequest. All that's left for us to do is to plug in your PasswordHandler.
We can't plug in your PasswordHandler directly, because it doesn't implement the CAS3 AuthenticationHandler API. However, LegacyPasswordHandlerAdaptorAuthenticationHandler adapts from CAS2 PasswordHandler to CAS3 AuthenticationHandler.
In CAS2, you declared the fully qualified name of your implementation of PasswordHandler in web.xml. Suppose your implementation was edu.someschoool.its.cas.MySpecialPasswordHandler . Then your web.xml included:
<context-param> <param-name>edu.yale.its.tp.cas.authHandler</param-name> <param-value>edu.someschoool.its.cas.MySpecialPasswordHandler</param-value> </context-param>
Instead of declaring this class name in web.xml, in CAS3 you'll declare it as part of the configuration of an LegacyPasswordHandlerAdaptorAuthenticationHandler instance plugged into the AuthenticationManager.
By default, the AuthenticationManager is configured in deployerConfigContext.xml. This is because even if you weren't plugging in a legacy CAS 2 PasswordHandler, you'd still be editing this file, to plug in some other AuthenticationHandler.
Step 3
Configure the AuthenticationManager to use a LegacyPasswordHandlerAdaptorAuthenticationManager configured to use your PasswordHandler.
<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl"> <property name="credentialsToPrincipalResolvers"> <list> <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" /> <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" /> </list> </property> <property name="authenticationHandlers"> <list> <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" /> <!-- | Here we declare that one of our AuthenticationHandlers is an instance of the CAS 2 PasswordHandler | adaptor. +--> <bean class="org.jasig.cas.adaptors.cas.LegacyPasswordHandlerAdaptorAuthenticationHandler"> <!-- | Here we give the adaptor a PasswordHandler to adapt. +--> <property name="passwordHandler"> <bean class="edu.someschoool.its.cas.MySpecialPasswordHandler"/> </property> </bean> </list> </property> </bean>
Where to put your files
Your PasswordHandler implementation must be available at runtime to the CAS web application. You can accomplish this by including your PasswordHandler's .class file in /WEB-INF/classes/... or its .jar in /WEB-INF/lib/. If your implementation is dependent upon other classes, they must also be included in /WEB-INF/classes/ or in /WEB-INF/lib/ . This is exactly the same as in CAS 2.
Using CAS2 TrustHandlers in CAS3
This page is primarily about using CAS2 PasswordHandlers in CAS 3, since in practice very few deployers if any used the CAS2 TrustHandler feature. TrustHandler allows authentication handlers that can authenticate a user other than that specified by the 'username' HttpServletRequest parameter and which evaluate aspects of the HttpServletRequest other than the username and password request parametrs. Here's a quick summary of how to run CAS2 TrustHandlers in CAS3:
Declare the credential and the CredentialBinder
<bean id="loginFormAction" class="org.jasig.cas.web.flow.LoginFormAction"> <property name="centralAuthenticationService" ref="centralAuthenticationService" /> <!-- | we add this property definition, which instructs Spring to | call setFormObjectClass() on the LogonFormAction instance we're configuring, | configuring it to use LegacyCasTrustedCredentials as the form class. +--> <property name="formObjectClass" value="org.jasig.cas.adaptors.cas.LegacyCasTrustedCredentials" /> <!-- | Here we're instructing Spring to call setCredentialsBinder() on the LogonFormAction instance, | feeding this property an instance of LegacyCasCredentialsBinder. | We use the same binder for LegacyCasTrustedCredentials as for LegacyCasCredentials. |--> <property name="credentialsBinder"> <bean class="org.jasig.cas.adaptors.cas.LegacyCasCredentialsBinder"/> </property> </bean>
Adapt and declare your TrustHandler
<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl"> <property name="credentialsToPrincipalResolvers"> <list> <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" /> <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" /> </list> </property> <property name="authenticationHandlers"> <list> <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" /> <!-- | Here we declare that one of our AuthenticationHandlers is an instance of the CAS 2 PasswordHandler | adaptor. +--> <bean class="org.jasig.cas.adaptors.cas.LegacyTrustHandlerAdaptorAuthenticationHandler"> <!-- | Here we give the adaptor a TrustHandler to adapt. +--> <property name="trustHandler"> <bean class="edu.someschoool.its.cas.MySpecialTrustHandler"/> </property> </bean> </list> </property> </bean>