InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

Access the Exchange store via WebDAV with Form-Based-Authentication turned on [Updated]

When a HTTP or WebDAV request is issued agains an Exchange 2003 or 2007 public folder or mailbox folder, the server returns a HTTP/1.1 440 Login Timeout error if Form Based authentication is enabled.

To work around this situation, you must do a logon to Outlook Web Access before performing any further requests. To do this, perform the following request against the exchange server:

    1 POST /exchweb/bin/auth/owaauth.dll HTTP/1.0

    2 Content-Type: application/x-www-form-urlencoded

    3 Connection: Keep-Alive

    4 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)

    5 Host: <Server>

    6 Content-Length: XXX

    7 

    8 destination=<destination-url>&username=<domain\\password>&password=<password>

Note: The url above is used with Exchange 2003. If want to authenticate against Exchange 2007 use this url:

    1 POST owa/auth/owaauth.dll

The Exchange 2003 url is still there but it won't work.

Replace the<destination-url> with the url of the uri where you want to do your request. The<domain\username> and the <password> fields must be replaced with the credential you want to use during your session.

When the login was successful, you will receive two cookies that you must pass along with all further requests. If no cookies are returned, the logon was not successful.

C# Example

Below is a sample code written in C#:

    1 privateHttpWebRequest GetRequestObject(string uri, string method)

    2 {

    3     HttpWebRequest webrequest;

    4     string[] credentials;

    5     CredentialCache cache;

    6     Uri _uri;

    7 

    8     // Initiate a new WebRequest to the given URI.

    9     _uri = newUri(uri);

   10     webrequest = (HttpWebRequest)System.Net.WebRequest.Create(_uri);

   11 

   12     webrequest.CookieContainer = newCookieContainer();

   13     webrequest.Method = method;

   14 

   15     return webrequest;

   16 }

   17 

   18 privateCookieCollection DoFormbasedAuthentication(string uri, NetworkCredential credential)

   19 {

   20     string server;

   21     HttpWebRequest request;

   22     HttpWebResponse response;

   23     byte[] body;

   24     Stream stream;

   25     string result;

   26 

   27     try

   28     {

   29         // Get the server portion of the requested uri and appen the authentication dll from Exchange

   30         server = uri.Substring(0, uri.IndexOf("/", 8)) + "/exchweb/bin/auth/owaauth.dll";

   31 

   32         request = GetRequestObject(server, "POST");

   33         request.CookieContainer = newCookieContainer();

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

   35 

   36         // Prepare the body of the request

   37         body = Encoding.UTF8.GetBytes(string.Format("destination={0}&username={1}\\{2}&password={3}",

   38             uri, credential.Domain, credential.UserName, credential.Password));

   39 

   40         request.ContentLength = body.Length;

   41 

   42         // Send the request to the server

   43         stream = request.GetRequestStream();

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

   45         stream.Close();

   46 

   47         // Get the response

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

   49 

   50         // Check if the login was successful

   51         if (response.Cookies.Count < 2) throw

   52             newAuthenticationException("Failed to login to OWA. Be sure your domain and password are correct.");

   53 

   54         return response.Cookies;

   55     }

   56     catch (AuthenticationException ex)

   57     {

   58         throw;

   59     }

   60     catch (Exception ex)

   61     {

   62         thrownewException("Failed to login to OWA. The following error occured: " + ex.Message, ex);

   63     }

   64 }

JavaScript Example

The same approach is possible with a small javascript.

Be sure to read this arcticle about the XmlHttp object: Permission Denied Error with XMLHTTP object

First, the main function for the example:

    1 var strCookies;

    2 var strRequest;

    3 var objXmlResult;

    4 

    5 try

    6 {

    7     strCookies = doFBALogin("https://exchangeserver/public", "exchangeserver", "domain\\username ", "password");

    8 

    9     strRequest = "<D:searchrequest xmlns:D = \"DAV:\" ><D:sql>SELECT \"DAV:displayname\" FROM \"https://exchangeserver/public\" WHERE \"DAV:ishidden\" = false</D:sql></D:searchrequest>";

   10 

   11     objXmlResult = Search("https://exchangeserver/public", strRequest, strCookies);

   12 

   13     // Do something with the XML object

   14 }

   15 catch (e)

   16 {

   17     // Handle the error!

   18 }

Now, do the actual work:

    1 function Search(strUrl, strQuery, strCookies)

    2 {

    3     // Send the request to the server

    4     var xmlHTTP = new ActiveXObject("Microsoft.xmlhttp");

    5     var i;

    6 

    7     xmlHTTP.open("SEARCH", strUrl, false);

    8     xmlHTTP.setRequestHeader("Content-type:", "text/xml");

    9 

   10     // Add the cookies to the request. According to Microsoft article Q234486, the cookie has to be set two times.

   11     xmlHTTP.setRequestHeader("Cookies", "Necessary according to Q234486");

   12     xmlHTTP.setRequestHeader("Cookies", strCookies);

   13     xmlHTTP.send(strQuery);

   14 

   15     return xmlHTTP.responseXML;

   16 }

   17 

   18 

   19 function doFBALogin(strDestination, strServer, strUsername, strPassword)

   20 {

   21     var xmlHTTP = new ActiveXObject("Microsoft.xmlhttp");

   22     var strUrl

   23         var strContent;

   24     var arrHeader;

   25     var strCookies;

   26     var intCookies;

   27     var i;

   28 

   29     // Prepare the URL for FBA login

   30     strUrl = "https://" + strServer + "/exchweb/bin/auth/owaauth.dll";

   31 

   32     xmlHTTP.open("POST", strUrl, false);

   33 

   34     xmlHTTP.setRequestHeader("Content-type:", "application/x-www-form-urlencoded");

   35 

   36     // Generate the body for FBA login

   37     strContent = "destination=" + strDestination + "&username=" + strUsername + "&password=" + strPassword;

   38     xmlHTTP.send(strContent);

   39 

   40     // Get all response headers

   41     arrHeader = xmlHTTP.getAllResponseHeaders().split("

   42         strCookies = "";

   43 

   44     intCookies = 0;

   45 

   46     // Iterate through the collection of returned headers

   47     for (i = 0; i<arrHeader.length; i++)

   48     {

   49         // If the entry is a cookies, extract the name/value

   50         if (arrHeader[i].indexOf("Set-Cookie") != -1)

   51         {

   52             strCookies += arrHeader[i].substr(12) + "; ";

   53             intCookies++;

   54         }

   55     }

   56 

   57     // Check if two cookies have been returned. Otherwise throw an exception

   58     if (intCookies < 2) throw"Could not log in to OWA!";

   59     return strCookies;

   60 }

Currently rated 3.5 by 4 people

  • Currently 3.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Exchange articles
Posted by Henning Krause on Thursday, December 30, 2004 6:00 PM, last modified on Tuesday, March 18, 2008 6:00 AM
Permalink | Comments (25) | Post RSSRSS comment feed

Comments