Hello,

First of all I want to thank all developers of CAS for their great work.
Second I would like to contribute some stuff I called generic http form
authenticator/ connector with a design extension to CAS for setting multiple login cookies across different domains (fqdn hosts) e.g. appl1.mydomain.com, appl2.mydomain.com and so on.

This extension is a more general authentication connector based on the
idea and the code of the outlook webaccess connector OWA
(cas-server-support-owa) found on the JA-SIG website.

The idea behind my code is to be able to run multiple authentication
connectors against each application which you are not able to casify in
the main way. For example if you could not modify any peace of the
application e.g. OWA or other closed source form based authenticated
applications but you want to have a central login site or portal entry
point.

The connector makes use of apache httpclient to get the login site,
parse the form data via jericho html parser and send valid credentials
and other stuff need to authenticate to the login site (of course you
have to use the same credentials like username and password for logging
into CAS and into the application). In the last step the session cookies
are send out and the user have already been authenticated when he is
browsing to the application (as long as the cookies are valid).

connection example:
<bean id="MyPortalConnection"
class="de.ditis.cas.support.http.GenericHttpFormConnector">
<property name="urlLogin" value="https://fqdn/login/LoginPage.aspx"; /> <property name="urlLoginForm" value="https://fqdn/login/LoginPage.aspx"; />
        <property name="urlLoginTest"
value="https://fqdn/protecteded/images/header_logo.gif"; />
        <property name="fieldNameUsername" value="txtAccount" />
        <property name="fieldNamePassword" value="txtPassword"
/>
...

There are other properties like: propModifyFormValues,
listDeleteFormValues, propAddHeaders to hande additional data
send to the login form. so you can override the form values, if there
are any JavaScripts on the login site of the application modifing the
input done via hidden fields for example.

configuration example:
login-webflow.xml (how to implement scope=session):

<!--  ApplicationXYZ Ticket  -->
<action-state id="sendApplicationXYZ">
    <action bean="sendApplicationXYZTicketAction" method="submit" />
    <transition on="success" to="sendTicketGrantingTicket" />
<transition on="error" to="sendTicketGrantingTicket" /> <!-- TODO log warning -->
</action-state>

cas-servlet.xml:

<bean id="sendApplicationXYZTicketAction" class="de.ditis.cas.support.http.SendGenericHttpFormAction" > <property name="genericHttpFormConnection" ref="ApplicationXYZConnection"/>
</bean>

<bean id="ApplicationXYZConnection" class="de.ditis.cas.support.http.GenericHttpFormConnector">
    <property name="urlLogin" value="https://app01.fqdn.com/"; />
<property name="urlLoginForm" value="https://app01.fqdn.com/login/login.aspx"; /> <property name="urlLoginTest" value="https://app01.fqdn.com/profile/tab_general.aspx"; />
    <property name="fieldNameUsername" value="login" />
    <property name="fieldNamePassword" value="password" />
    <!-- modify form fields done on client side e.g. by JavaScript -->
    <property name="modifyFormValues">
        <map>
            <entry>
                   <key><value>bscriptenabled</value></key>
                   <value>true</value>
            </entry>
         </map>
    </property>
    <!-- add nessessary header for requests -->
    <property name="addHeaderValues">
        <map>
         <entry>
           <key><value>Host</value></key>
           <value>app01.fqdn.com</value>
         </entry>
        </map>
    </property>
    <!-- which form fields should not be send to login form action -->
    <property name="deleteFormValues">
        <list>
            <value>languageid</value>
        </list>
    </property>
    <!-- which cookies must we get back for login validation -->
    <property name="mustHaveCookiesRegex">
        <list>
            <value>my_hero_user_\d+_session</value>
        </list>
    </property>
    <property name="crossDomainCookieStore">
        <ref bean="crossDomainCookieStore" />
    </property>
</bean>

<bean id="dynamicRedirectViewSelector" scope="session" class="de.ditis.cas.web.flow.DynamicRedirectViewSelector"> <!-- for reading cookies which have to be send out to different domains -->
    <property name="crossDomainCookieStore">
        <ref bean="crossDomainCookieStore" />
    </property>
</bean>

<bean id="crossDomainCookieStore" scope="session" class="de.ditis.cas.web.CrossDomainCookieStore">
    <property name="domainSingleSignOnSetCookieMapping">
        <map>
        <!--
         <entry>
           <key><value>www.domain.com</value></key>
           <value>https://sso.app01.domain.com/cas/ssosc</value>
           or
           <value>https://app01.domain.com/cas/ssosc</value>
         </entry>
          -->
        </map>
    </property>
</bean>

If your applications are running on multiple domains and you must share
the login cookies your application is providing, you can take my
solution, which extends the webflow (dynamicRedirectViewSelector) not
redirecting direct to the application. instead you will be redirect to a
redirector site setting the cookies via multiple <img tags pointing to
scripts on the other server which include the cookie setting logic and
finaly you are redirect, after the cookies are send out to the browser
from the correct fqdn.

Further improvements/ features:
if there is no way to install the cookie setting logic direct on the
application server or you can not use any reverse proxy mechanism you
can do the following trick (i your application can hand domain cookies):
1.) register a subdomain in DNS e.g. sso.application.yourdomain
     pointing via the IP to the CAS Server
2.) the single sign on set cookie logic can now set cookies for
     .application.yourdomain

btw. some apache config hacks to achieve the above:
# proxy cas from apache to tomcat:
RewriteRule ^/cas/ssosc(.*)$
  https://127.0.0.1:8443/cas/ssosc$1 [NC,NE,P,L]

# rewrite send out cookies (remove domain attribute for host cookies)
Header edit Set-Cookie \
^ASP.NET_SessionId(.*)Domain=fqdn.your.host;.(.*)$ \
"ASP.NET_SessionId$1$2"

# remove "" at the beginning and end of cookies values sun/apache does, microsoft does not
Header edit Set-Cookie  ^(.*)=\"(.*)\";(.*)$    "$1=$2;$3"

I know this approach will break with the main CAS idea, but if anybody
wants to run a more compatible SSO solution for not modifyable
applications, this extension may help.

Last I want to sorry for my poor english and you must know that I'm relative new to j2ee and spring and the other great things used to implement CAS.

Any hints about the design, code and security issues are welcomed :-)
(of course this code is not ready to production in this early stage, but
I will use it as soon as possible)

by the way I would like to implement some security design improvments:
* how can I run multiple beans e.g. crossDomainCookieStore in Session
  Scope, so that every Web Session get's its own store?
* whats the way to upload my prototyping code (or should I send it to
  the list?)

bye martin

--
You are currently subscribed to cas-dev@lists.jasig.org as: 
arch...@mail-archive.com
To unsubscribe, change settings or access archives, see 
http://www.ja-sig.org/wiki/display/JSG/cas-dev

Reply via email to