CAS Tips & Troubleshooting
Tips
CAS JDBC deployerConfigContext.xml
These are instructions to configure CAS to use JDBC for usernames and passwords.
- Add the following bean to deployerConfigContext.xml, changing values where applicable:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/hibernate</value> </property> <property name="username"> <value>hibuser</value> </property> <property name="password"> <value>password</value> </property> </bean>
- Replace the default SimpleTestUsernamePasswordAuthenticationHandler bean with this bean, changing values where applicable:
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> <property name="dataSource" ref="dataSource" /> <property name="sql" value="select PASSWORD from USERS where lower(USERNAME) = lower(?)" /> </bean>
CAS LDAP deployerConfigContext.xml
These are instructions to configure CAS to use LDAP for usernames and passwords.
- Add the following bean to deployerConfigContext.xml, changing values where applicable:
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource"> <property name="pooled" value="false"/> <property name="urls"> <list> <value>ldap://localhost:10389</value> </list> </property> <property name="userDn" value="uid=admin,ou=system"/> <property name="password" value="secret"/> <property name="baseEnvironmentProperties"> <map> <entry key="java.naming.security.authentication" value="simple" /> </map> </property> </bean>
- Replace the default SimpleTestUsernamePasswordAuthenticationHandler bean with this bean, changing values where applicable
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler"> <property name="filter" value="uid=%u" /> <property name="searchBase" value="ou=users,ou=system" /> <property name="contextSource" ref="contextSource" /> </bean>
Troubleshooting
Note: Some of the items on this page are only applicable if you are configuring a new CAS server.
Enabling SSL on the CAS server
See Enabling SSL on the CAS server.
Enable Logging
The recommended first step is to enable security logging. This is described in Turning on Security Logging. If running JBoss, you should also enable JBoss' security logging. Add the following snippet to server/default/conf/jboss-log4j.xml
.
<category name="org.jboss.security"> <priority value="TRACE" class="org.jboss.logging.XLevel"/> </category>
References
Redirect Loop
The Firefox error below can occur when your SSL certificate is not setup correctly or when your Spring Security config is incorrect. (Internet Explorer also fails but the error message is generic.)
Essentially, Firefox has detected an infinite loop of redirects. Causes of this problem can be:
- This can happen with self-signed certificates and is due to the fact that the
tomcat
entry in the keystore used by Tomcat (as specified inserver.xml
) is not the same entry incacerts
. In other words, thetomcat
entry is not trusted by the JVM. Follow the steps outlined in Trusting the Certificate to verify that the fingerprints match. - This can also occur when you do not have a
CasAuthenticationProvider
defined in your config. - The "CAS failed" URL (e.g.
/pentaho/casFailed
) might be protected. Combine that bug with a ticket validation failure and the result will be an infinite redirect where CAS says "userx is already logged in so redirect back" and Pentaho says "I don't know who you are and this page is protected so redirect."
More than one entry in %USER_HOME%/.keystore
The Tomcat documentation states that the keyAlias
attribute is required (on the Connector
element in server.xml
) if you have more than one entry in %USER_HOME%/.keystore
.
"Add this element [PentahoDoc:
keyAlias
] if your have more than one key in the KeyStore. If the element is not present the first key read in the KeyStore will be used."
jsessionid in service URL
Warning: This tip is only applicable if you are using a version of CAS prior to version 3.0.5.
org.springframework.security.ui.cas.CasProcessingFilterEntryPoint
calls request.encodeURL()
when constructing the redirect to the CAS login page. When constructing URLs that will be given to the browser, it is good practice to use request.encodeURL()
. This ensures that browsers with cookies disabled will still be able to maintain a session on the server. If Tomcat determines that the browser does not support cookies, Tomcat appends a parameter named jsessionid
to URLs created with request.encodeURL()
. (If the browser does support cookies, the jsessionid
is stored in a cookie which doesn't appear in URLs.)
org.apache.catalina.connector.Response
, Tomcat's HttpServletResponse
implementation, contains the following logic as documented in the javadoc of its isEncodeable()
method. This method is called by encodeURL()
.
Return true if the specified URL should be encoded with a session identifier. This will be true if all of the following conditions are met:
- The request we are responding to asked for a valid session
- The requested session ID was not received via a cookie
- The specified URL points back to somewhere within the web application that is responding to this request
So why all of this background information? Because it's possible that a service, when redirecting to the CAS login page, does not know if the browser can accept cookies yet, and must therefore append the jsessionid
to the service URL. When Spring Security goes to validate the ticket, you'll get a BadCredentialsException
with a root cause of INVALID SERVICE
. Why? Because the service value in the Spring Security {{org.springframework.security.ui.cas.ServiceProperties
}} does not have a jsessionid
value in it (but the service value given to CAS does) and therefore the compare fails.
There are several ways to address this problem:
- Upgrade to CAS 3.0.5 or later. The CAS team has already addressed this issue in CAS-360. Also see SEC-306 for its relation to Spring Security.
- Do not create a session before the
CasProcessingFilterEntryPoint
runs. For this, you'll need to disallow the creation of sessions withinorg.springframework.security.ui.ExceptionTranslationFilter
(in addition to any session creation done within other filters). Set thecreateSessionAllowed
property tofalse
as in the example below:The downside to this solution is that your original request is not saved (because the filter has nowhere (e.g. a session) to save it).<bean id="exceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter"> <property name="authenticationEntryPoint"> <ref local="authenticationProcessingFilterEntryPoint" /> </property> <property name="accessDeniedHandler"> <bean class="org.springframework.security.ui.AccessDeniedHandlerImpl" /> </property> <property name="createSessionAllowed" value="false" /> </bean>
Note: Even though you might disallow session creation in
ExceptionTranslationFilter
, other filters (even your own filters unrelated to security) might be creating a session, which will force ajsessionid
to be appended to the service URL. You'll need to eliminate the session creation in those filters for this workaround to work.
References
503
If you get 503 for an XHTML DTD then you are most likely using an incorrect CAS service ticket validator URL.
unable to find valid certification path to requested target
If you get this message in the server log, you most likely did not execute the "Trusting the Self-Signed Certificate" instructions on Enabling SSL on the CAS Server. Make sure that the cacerts keystore into which you are importing belongs to the JDK running Tomcat.