Pudpuduk
Pudpuduk

Reputation: 1609

Setting up CAS Jasig Server with database authentication

I am trying to setup Single Sign-On via a CAS server. I want to use database authentication as I have existing applications using spring security that authenticate through MySQL.

I am following the instructions on the official site, using their base maven overlay project as my starting point. Adding a database authentication handler seems straightforward from the instructions on the site - define the beans( db handler, password encoder and datasource) and add the handler to the list of handlers on the authenticationManager bean.

When I try to login on /cas/login, nothing happens. No query hits the database, as if the handler is not considered at all. The web page does not spit out an error about wrong credentials. The tomcat log does not give any errors or any signs of whats wrong and I am at a loss. What else do I need to setup?

My deployerConfigContext.xml is below. I have only edited/added stuff up to passwordEncoder. Everything else is from the default config that comes with the maven overlay project.

Thank you for your help and Happy New Year!

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:c="http://www.springframework.org/schema/c"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns:sec="http://www.springframework.org/schema/security"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
   http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<!--
   | The authentication manager defines security policy for authentication by specifying at a minimum
   | the authentication handlers that will be used to authenticate credential. While the AuthenticationManager
   | interface supports plugging in another implementation, the default PolicyBasedAuthenticationManager should
   | be sufficient in most cases.
   +-->
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
    <constructor-arg>
        <list>
        <ref bean="dbAuthHandler" />
     </list>
    </constructor-arg>

    <!-- Uncomment the metadata populator to allow clearpass to capture and cache the password
         This switch effectively will turn on clearpass.
    <property name="authenticationMetaDataPopulators">
       <util:list>
          <bean class="org.jasig.cas.extension.clearpass.CacheCredentialsMetaDataPopulator"
                c:credentialCache-ref="encryptedMap" />
       </util:list>
    </property>
    -->

    <!--
       | Defines the security policy around authentication. Some alternative policies that ship with CAS:
       |
       | * NotPreventedAuthenticationPolicy - all credential must either pass or fail authentication
       | * AllAuthenticationPolicy - all presented credential must be authenticated successfully
       | * RequiredHandlerAuthenticationPolicy - specifies a handler that must authenticate its credential to pass
       -->
    <property name="authenticationPolicy">
        <bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy" />
    </property>
</bean>

<!--
   | TODO: Replace this component with one suitable for your enviroment.
   |
   | This component provides authentication for the kind of credential used in your environment. In most cases
   | credential is a username/password pair that lives in a system of record like an LDAP directory.
   | The most common authentication handler beans:
   |
   | * org.jasig.cas.authentication.LdapAuthenticationHandler
   | * org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler
   | * org.jasig.cas.adaptors.x509.authentication.handler.support.X509CredentialsAuthenticationHandler
   | * org.jasig.cas.support.spnego.authentication.handler.support.JCIFSSpnegoAuthenticationHandler
   -->
<bean id="dbAuthHandler"    class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler">
  <property name="dataSource" ref="secureDataSource"></property>
  <property name="passwordEncoder" ref="passwordEncoder"></property>
  <property name="tableUsers" value="sec_user"></property>
  <property name="fieldUser" value="username"></property>
  <property name="fieldPassword" value="password"></property>
</bean>

<bean id="secureDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
   <property name="driverClassName" value="${secure.db.driver}"/>
   <property name="url" value="${secure.db.url}"/>
   <property name="username" value="${secure.db.username}"/>
   <property name="password" value="${secure.db.password}"/>
   <property name="maxActive" value="${secure.db.max.active}"/>
   <property name="maxIdle" value="${secure.db.max.idle}"/>
   <property name="minIdle" value="${secure.db.min.idle}"/>
   <property name="testOnBorrow" value="${secure.db.testOnBorrow}"></property>
   <property name="validationQuery" value="select 1"></property>
</bean>

<bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">
   <constructor-arg value="SHA256"></constructor-arg>
   <property name="characterEncoding" value="UTF-8"></property>
</bean>

<!-- Required for proxy ticket mechanism -->
<bean id="proxyPrincipalResolver"
      class="org.jasig.cas.authentication.principal.BasicPrincipalResolver" />

<!--
   | Resolves a principal from a credential using an attribute repository that is configured to resolve
   | against a deployer-specific store (e.g. LDAP).
   -->
<bean id="primaryPrincipalResolver"
      class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
    <property name="attributeRepository" ref="attributeRepository" />
</bean>

<!--
Bean that defines the attributes that a service may return.  This example uses the Stub/Mock version.  A real implementation
may go against a database or LDAP server.  The id should remain "attributeRepository" though.
+-->
<bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
        p:backingMap-ref="attrRepoBackingMap" />

<util:map id="attrRepoBackingMap">
    <entry key="uid" value="uid" />
    <entry key="eduPersonAffiliation" value="eduPersonAffiliation" /> 
    <entry key="groupMembership" value="groupMembership" />
</util:map>

<!-- 
Sample, in-memory data store for the ServiceRegistry. A real implementation
would probably want to replace this with the JPA-backed ServiceRegistry DAO
The name of this bean should remain "serviceRegistryDao".
+-->
<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"
        p:registeredServices-ref="registeredServicesList" />

<util:list id="registeredServicesList">
    <bean class="org.jasig.cas.services.RegexRegisteredService"
          p:id="0" p:name="HTTP and IMAP" p:description="Allows HTTP(S) and IMAP(S) protocols"
          p:serviceId="^(https?|imaps?)://.*" p:evaluationOrder="10000001" />
    <!--
    Use the following definition instead of the above to further restrict access
    to services within your domain (including sub domains).
    Note that example.com must be replaced with the domain you wish to permit.
    This example also demonstrates the configuration of an attribute filter
    that only allows for attributes whose length is 3.
    -->
    <!--
    <bean class="org.jasig.cas.services.RegexRegisteredService">
        <property name="id" value="1" />
        <property name="name" value="HTTP and IMAP on example.com" />
        <property name="description" value="Allows HTTP(S) and IMAP(S) protocols on example.com" />
        <property name="serviceId" value="^(https?|imaps?)://([A-Za-z0-9_-]+\.)*example\.com/.*" />
        <property name="evaluationOrder" value="0" />
        <property name="attributeFilter">
          <bean class="org.jasig.cas.services.support.RegisteredServiceRegexAttributeFilter" c:regex="^\w{3}$" /> 
        </property>
    </bean>
    -->
</util:list>

<bean id="auditTrailManager" class="com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager" />

<bean id="healthCheckMonitor" class="org.jasig.cas.monitor.HealthCheckMonitor" p:monitors-ref="monitorsList" />

<util:list id="monitorsList">
  <bean class="org.jasig.cas.monitor.MemoryMonitor" p:freeMemoryWarnThreshold="10" />
  <!--
    NOTE
    The following ticket registries support SessionMonitor:
      * DefaultTicketRegistry
      * JpaTicketRegistry
    Remove this monitor if you use an unsupported registry.
  -->
  <bean class="org.jasig.cas.monitor.SessionMonitor"
      p:ticketRegistry-ref="ticketRegistry"
      p:serviceTicketCountWarnThreshold="5000"
      p:sessionCountWarnThreshold="100000" />
</util:list>

UPDATE: For debugging purposes, here are two log files. One with the deployerConfig you see here, and one with the default one.

Mine: http://pastebin.com/9tRLPDq8

Default: http://pastebin.com/pxrUJMQG

In the default case I use wrong credentials on purpose. The most notable differences that I see are right before the audit(?) message:

Mine:

2015-01-02 09:58:15,515 DEBUG [org.springframework.webflow.execution.ActionExecutor] - <Executing [EvaluateAction@cdb588 expression = authenticationViaFormAction.submit(flowRequestContext, flowScope.credential, messageContext), resultExpression = [null]]>
2015-01-02 09:58:15,515 DEBUG [org.springframework.webflow.execution.AnnotatedAction] - <Putting action execution attributes map[[empty]]>
2015-01-02 09:58:15,515 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Returning cached instance of singleton bean 'authenticationViaFormAction'>
2015-01-02 09:58:15,517 INFO [org.perf4j.TimingLogger] - <start[1420221495517] time[0] tag[AUTHENTICATE]>
2015-01-02 09:58:15,518 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
...

Default:

2015-01-02 10:07:53,246 DEBUG [org.springframework.webflow.execution.AnnotatedAction] - <Putting action execution attributes map[[empty]]>
2015-01-02 10:07:53,246 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Returning cached instance of singleton bean 'authenticationViaFormAction'>
2015-01-02 10:07:53,266 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Returning cached instance of singleton bean 'auditTrailManagementAspect'>
2015-01-02 10:07:53,267 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Returning cached instance of singleton bean 'timingAspect'>
2015-01-02 10:07:53,272 DEBUG [org.jasig.cas.authentication.AcceptUsersAuthenticationHandler] - <admin was not found in the map.>
2015-01-02 10:07:53,272 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <AcceptUsersAuthenticationHandler failed authenticating admin+password>
2015-01-02 10:07:53,272 INFO [org.perf4j.TimingLogger] - <start[1420222073269] time[2] tag[AUTHENTICATE]>
2015-01-02 10:07:53,277 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
...

UPDATE 2: I digged into the source a bit and compared the log messages to the expected ones. Looking at the authenticateInternal method, I do not see any of the log messages there when using the db handler, and I see them when I use the default handler. Assuming I actually reach this method, the only place where it can fail without a message appears to be for (final Credential credential : credentials) {...}.

Adding system info: CAS 4.0.0 Tomcat 7 JDK 1.7 MySQL 5.5.22

UPDATE 3: Well, it was looking at me right there all along...

WHO: audit:unknown
WHAT: java.security.NoSuchAlgorithmException: SHA256 MessageDigest not available**
ACTION: TICKET_GRANTING_TICKET_NOT_CREATED
APPLICATION: CAS
WHEN: Fri Jan 02 09:58:15 PST 2015
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1

Upvotes: 2

Views: 5099

Answers (1)

jleleu
jleleu

Reputation: 2699

Disclaimer: I'm the Chairman of CAS and founder of CAS in the cloud (https://www.casinthecloud.com).

Strange! The configuration looks good. Are you sure the overlay is properly built (overrided deployerConfigContext.xml file in the right directory)?

You should already have INFO logs in the cas.log file (https://github.com/Jasig/cas/blob/4.0.x/cas-server-webapp/src/main/resources/log4j.xml). Take a look at these logs...

Upvotes: 2

Related Questions