CASifying Outlook Web Access 2

New Release 3.4.2

5/19/2010 New Release of the original CASifying Outlook Web Access 2 to support 3.4.2 cas-server-support-owa.3.4.2.tar.gz
All credit for this module goes to  Matthieu MARC all I did was updates.To clarify the difference between this solution and the .NET solution: In the .NET the ASP code must be installed on the OWA server but after the user login there is no load on the CAS serverIn this solution the CAS web server acts as a proxy (see this explination) for all traffic to the OWA server so there are no changes needed on the OWA server but all OWA traffic goes through the CAS server after login.

New Native .NET CAS Client for OWA

The .NET CAS Client for OWA is based on approach described below, but without the Apache rewrite rules or any patches to the CAS Server. The CAS Client for OWA builds on the new CAS ClearPass extension and provides a lightweight authentication shim that can be deployed on the same server as OWA.

http://github.com/wgthom/CasOwa

Another solutions to CASify OWA.

CAS and OWA at Arts et Métiers ParisTech (France)

Goal

My problem was to be able to use CAS with my network architecture in which there was an OWA server. There were two solutions, but they were for me not good : I did not want to store all users passwords in a local database, and I did not want to use the cas2owa ISAPI filter which is for me a working hack, but a hack.

My idea is simple : when a user connect to OWA, he get a cookie which let him connect again to OWA without authenticating again (it will be boring to authenticate to each page he want to see). So, if I want to get this cookie, I need the user login and password. I don't want to store user's login and password nowhere. So, the only way to get the OWA cookie is to use the user's login and password when I got it, when the user is authenticating against CAS server. I can't change OWA, but I can change CAS. So I did.

? Cas is working like this :

 1. User is connecting to login page

 2. User is entering login and password

 3. CAS is checking login and password

 4. If ok, then CAS return the CAS cookie containing the Granting Ticket.

? My change are :

 1. User is connecting to login page

 2. User is entering login and password

 3. CAS is checking login and password

 4. If ok, then CAS use login and password to authenticate against OWA service and retrieve OWA cookie

 5. If ok, then CAS return the CAS cookie containing the Granting Ticket and the OWA cookie.

So I opened Eclipse and starting to read CAS code (smile)

 Prerequesite

OWA must be running in Form Authentication Based, so when users are connecting to OWA, there must have first a page with an authentication form.

URL to access OWA must be like : https://owa.domain.com/exchange/? to access mailboxes and https://owa.domain.com/exchweb/.../? to access Form Authentication Page.

Change in CAS 3.2 and CAS 3.3.1

You can get the patchfor CAS 3.2 in Attachments : filename is cas-3.2.1-owa.patch

You can get the patchfor CAS 3.3.1 in Attachments : filename is cas-3.3.1-owa.patch

 I used Cygwin to create the patch (diff), and to apply the patch (patch).

Apply the patch and compile using maven.

Architecture

The system architecture must be strict in order to make the system work. The goal is that either cas server and owa server have the same hostname (so cookies can be accepted by your web browser). So to do, I use Apache and mod_proxy. If you are using Windows system, download the Apache + SSL package.

Let's have two server : cas.domain.com and owa.domain.com. In the DNS system I had two entry : webmail.domain.com and cas.domain.com. User will use https://webmail.domain.com/ to access OWA mailboxes, and https://cas.domain.com/cas/ to authenticate. Webmail.domain.com point to apache+mod_proxy service which redirect all request to OWA server. Cas.domain.com point to tomcat service. Cas will generate OWA cookies in domain domain.com.

Why using a reverse proxy server ? to be able to change some configuration without changing the OWA server (for example to delete the cookies made by OWA when the user  connect to OWA webmail interface, or to redirect the user to the CAS logout page when user click on "disconnect" in OWA webmail interface).

Webmail.domain.com

In Apache, I configured a SSL Virtual Hosts and activated the mod_proxy, mod_proxy_http, , mod_proxy_connect and mod_rewrite

In the SSL Virtual Hosts definition, add the following directives for the webmail service :

<VirtualHost *:443>
    [...]
    SSLProxyEngine on
    ProxyPreserveHost on
    ServerSignature Off
    AllowCONNECT 443

    RewriteEngine on
    # redirect the user to the CAS logout page when he click on "logout" button in OWA interface
    RewriteCond %{QUERY_STRING} logoff
    RewriteRule ^/exchange/.+/ https://cas.domain.com/cas/logout?service=https://cas.domain.com/cas? [R]
    # redirect the user to the CAS login page when he want to access OWA interface without authentication information (OWA cookies)
    RewriteRule ^/exchweb/bin/auth/owalogon.asp https://cas.domain.com/cas/login?service=https://owa.domain.com/? [R]

    ProxyRequests off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    Header unset Set-Cookie
    
    ProxyPass /            https://real-owa-server/
    ProxyPassReverse /        https://real-owa-server/
        
    SetEnv force-proxy-request-1.0 1
    SetEnv proxy-nokeepalive 1
</VirtualHost>

"Header unset Set-Cookie" is important.OWA Cookies generated by CAS OWA module are for .domain.com domain. When connecting to OWA webmail interface, OWA Server will resend back cookies in domain.com domain (without .dot). The unset Set-Cookie directive will delete the cookie sent back by OWA Server. Otherwise, client will have two same cookies in different domain.

Cas.domain.com

You must install CAS server with cas-server-support-owa (compile with maven).

New files are :

WEB-INF\lib\cas-server-support-owa-3.3.1.jar
WEB-INF\spring-configuration\OWACadataCookieGenerator.xml
WEB-INF\spring-configuration\OWASessionCookieGenerator.xml

Modified file are :

WEB-INF\login-webflow.xml
WEB-INF\cas-servlet.xml

OWACadataCookieGenerator.xml (and OWASessionCoookieGenerator.xml)

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    <bean id="OWACadataCookieGenerator"
        p:cookieSecure="true"
        p:cookieMaxAge="-1"
        p:cookieName="cadata"
        p:cookieDomain="domain.com"
        p:cookiePath="/" />
</beans>

This two file are used to generate the two OWA cookies. You need to change p:cookieDomain in the two file according to your system. Make sure p:cookieDomain value include owa et cas server (domain.com include webmail.domain.com and cas.domain.com, so web browser will accept the cookies).

login-webflow.xml

Changed are made by the patch.

<action-state id="submit">
 <action bean="authenticationViaFormAction" method="submit" />
  <transition on="warn" to="warn" />
  <transition on="success" to="sendOwaTicket" />
  <transition on="error" to="viewLoginForm" />
</action-state>

<action-state id="sendOwaTicket">
 <action bean="sendOwaTicketAction" method="submit" />
  <transition on="success" to="sendTicketGrantingTicket" />
</action-state>

<action-state id="sendTicketGrantingTicket">
  <action bean="sendTicketGrantingTicketAction" />
  <transition on="success" to="serviceCheck" />
</action-state>

The action-state sendOwaTicket is included between submit(success) and sendTicketGrantingTicket.

cas-servlet.xml

The logout mapping is changed to include OWA logout (which delete OWA cookies)

<bean id="handlerMappingC" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
 <property name="mappings">
    <props>
       <prop key="/logout">
            logoutControllerSupportOWA
       </prop>
\[...\]

<bean id="logoutControllerSupportOWA" class="org.jasig.cas.support.owa.LogoutControllerSupportOWA"
     p:centralAuthenticationService-ref="centralAuthenticationService"
     p:logoutView="casLogoutView"
     p:warnCookieGenerator-ref="warnCookieGenerator"
     p:OWASessionCookieGenerator-ref="OWASessionCookieGenerator"
     p:OWACadataCookieGenerator-ref="OWACadataCookieGenerator"
     p:followServiceRedirects="true"
     p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator" />

The OWAConnection bean is configured in this file too :

<bean id="OWAConnection"
   p:host="real-owa-server"
   p:port="443"
   p:scheme="https"
   p:owaauth="/exchweb/bin/auth/owaauth.dll"
   p:owalogon="/exchweb/bin/auth/owalogon.asp"
   p:trusted="4"
   p:flags="4"
   p:destination="/exchange/"
/>

Change the p:host according to your system (put your OWA real server). The p:flags configuration with value 4 means that the connection is a public connection (to be sure that the OWA cookie will expire after the CAS cookie).

How to debug ?

I use Firefox, Firebug (to see urls call, http header and OWA response) and AnEC Cookie Editor (to play with cookies).