Use a proxy page to realize OWA Single Sign-on

 

In a production environment, if customer sets Exchange OWA (Outlook Web Access) behind some external portal, after sign in the web portal, when access the OWA, most users don’t like re-type user name and password. We call this requirement as OWA SSO (Single Sign-on).

 

To achieve this goal, if the web portal is developed by SharePoint Server, we can leverage SharePoint SSO service. Many articles discussed this before:

 

https://technet.microsoft.com/en-us/library/cc262932.aspx 
https://deewaker-blogs.blogspot.com/2009/06/owa-sharepoint-integration-tricky.html
https://blogs.msdn.com/tconte/archive/2007/01/17/owa-web-part-with-single-sign-on.aspx

However, if the web portal was developed by different techniques, and we have no SharePoint SSO service, can we make this happen alternatively with reasonable efforts?

 

What I’m trying to do in this article is to use a proxy page, which will complete below tasks:

 

1. When a client request(1) comes to the proxy page

2. The proxy page uses HttpWebRequest to send POST request to the owaauth.dll, you can set your preferred account at this part. The function name is DoExchangeFBA, which is used
to simulate the From Based Authentication.
3. Get the secure cookies in Cookies container, which is responded from OWA.
4. In Page_Load function, convert the returned cookie as httpcookie, and store it to HttpResponse.
5. Redirect to OWA, now the request(2) has OWA required cookies. This step needs to put the proxy page in the same site as the OWA, otherwise cookie will be removed by IE when redirecting the request (1). And OWA must be Form Authentication Mode.

 

The request flow is:

 

a. Provide login Info

b. Post to OWA

c. Get Authenticated Cookies from OWA

d. Send requests with Authenticated Cookies

 

Client -----[a]-----àProxy Page-----[b]-----àOWA-----[c]-----àClient-----[d]-----àOWA

 

Below is sample code of the proxy page for your reference, the key is to use CookieContainer get the cookie from OWA and convert it to the HttpCookie,so that client can use the HttpCookie in next redirected request.

 

This method can be used to other SSO scenarios when the second site supports Form Based Authentication. When use the proxy page, please be careful on make the user login information secure.

 

 

 

public partial class _Default : System.Web.UI.Page

 

{

    CookieCollection DoExchangeFBA(string server, string userName, string password)

{

    string uri = server + "/owa/auth/owaauth.dll";

 

    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);

 

    request.Method = "POST";

    request.CookieContainer = new CookieContainer();

    request.ContentType = "application/x-www-form-urlencoded";

    request.AllowAutoRedirect = false;

    request.ServicePoint.Expect100Continue = false;

   

    server = HttpUtility.UrlEncode(server);

 

    userName = HttpUtility.UrlEncode(userName);

    password = HttpUtility.UrlEncode(password);

    string bodyString = "destination={0}&flags=0&username={1}";

    bodyString += "&password={2}&SubmitCreds=Log+On&";

    bodyString += "forcedownlevel=0&trusted=0&isUtf8=1";

 

    bodyString = string.Format(bodyString, server,

                                userName, password);

    byte[] body = Encoding.ASCII.GetBytes(bodyString);

    request.ContentLength = body.Length;

    ServicePointManager.Expect100Continue = false;

    Stream stream = request.GetRequestStream();

    stream.Write(body, 0, body.Length);

    stream.Close();

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

 

    if (response.Cookies.Count < 2) throw

        new AuthenticationException("Failed to login to OWA!");

    return response.Cookies;

}

 

public static bool AcceptAllCertificatePolicy(object sender,

X509Certificate certificate,

X509Chain chain,

SslPolicyErrors sslPolicyErrors)

{

return true;

}

protected void Page_Load(object sender, EventArgs e)

{

ServicePointManager.ServerCertificateValidationCallback +=

AcceptAllCertificatePolicy;

CookieCollection CookieCol = DoExchangeFBA("https://" + "mailserver",

"domain\\user", "p@ssw0rd");

int i = 0;

foreach (Cookie cookie in CookieCol)

{ // Access to each cookie here

System.Web.HttpCookie Hcookie = new

System.Web.HttpCookie(cookie.Name, cookie.Value);

Hcookie.Expires = cookie.Expires;

Response.Cookies.Add (Hcookie);

i++;

}

Response.Redirect("https://mailserver/owa/");

}

 

           

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Happy New Year!

 

Best Regards,

 

Freist Li