Authenticating programmatically to Exchange Server 2003 FBA

In one of my projects I had to read data from Exchange Server 2003 programmatically. I had access to Outlook Web Access that used Form Based Authentication (FBA). After some hacking and testing I got authentication part of my utility work. The point was easy – before making WebDAV requests to Exchange Server we need authentication cookies, so there is active session we can use.

At first let’s see namespaces I used in my code to get FBA stuff work.

using System.Text;
using System.Net;
using System.Security.Authentication;
using System.Web;

And here is the authentication method that returns session cookies if authentication succeeded. You can use these cookies if you have to execute WebDAV queries by example.

private CookieCollection DoExchangeFBA(string server, string userName, string password)
{
   
var uri = server + "/exchweb/bin/auth/owaauth.dll"
;

   
var 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);
   
var bodyString = "destination={0}&flags=0&username={1}"
;
    bodyString +=
"&password={2}&SubmitCreds=Log+On&"
;
    bodyString +=
"forcedownlevel=0&trusted=0"
;
    bodyString =
string
.Format(bodyString, server,
                                userName, password);

   
var body = Encoding
.ASCII.GetBytes(bodyString);

    request.ContentLength = body.Length;
   
ServicePointManager.Expect100Continue = false
;

   
var
stream = request.GetRequestStream();
    stream.Write(body, 0, body.Length);
    stream.Close();

   
var response = (HttpWebResponse
)request.GetResponse();
   
if (response.Cookies.Count < 2) throw
        new AuthenticationException("Failed to login to OWA!"
);

   
return response.Cookies;
}

If you are using Exhange Server 2007 then you have different authentication address and you get back only one cookie.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    17 thoughts on “Authenticating programmatically to Exchange Server 2003 FBA

    • December 17, 2008 at 4:17 pm
      Permalink

      Hi Gunnar,

      Thanks for the post, I’ve tried your code (and some similar code I’ve written) but just get a 400 bad request back from the server when I try to make use of the cookieCollection:

      Request.CookieContainer.Add(DoExchangeFBA(“https://” + mailboxServer, “nwtraders\\dave hope”, “Password”));

      The raw http request looks like the following:

      PROPFIND /exchange/owatest@nwtraders.msft/non_ipm_subtree/ HTTP/1.1

      Host: exchange.nwtraders.msft

      Cookie: sessionid=7a7c69df-0455-4g58-a96e-4e72388f4efa:000; cadata=”1lsLZBvnfDk/Np9dfgFFtfgT91xl9UMjTsf7YxJ7IUufEVYQCm443d7qqxqvafmPKELKxT9yQFeG/2SFN0fTOAv6Q==”

      Content-Length: 141

      Expect: 100-continue

      <?xml version=”1.0″?><a:propfind xmlns:a=”DAV:” xmlns:d=”schemas.microsoft.com/exchange/”><a:prop><d:oof-state/></a:prop></a:propfind>

      Any ideas as to where I’m going wrong?

      Thanks,

      Dave

    • December 19, 2008 at 2:14 am
      Permalink

      I have seen this error in rather weird situation. I wrote command line application that imports calendars data from Exchange to SharePoint. Everything worked fine. I decided to create SharePoint server timer job based on this code. Without any markable modifications this code is not able to work under SharePoint timer process. After authentication it always gets error 400 bad request.

      Can you tell me more about your technical environment? Maybe it is possible to find out what is going on

    • December 22, 2008 at 9:17 am
      Permalink

      Thanks for the response!

      We have multiple exchange servers. The code works fine against those which use Negotiate authentication but not those using FBA.

      The code fails when making the request from the exchange servers itself. It’s Exchange 2003 with all updates applied running on Windows 2k3 SP2 (again, with all updates applied).

      Is there any specific information I can provide?

      Thanks!

      Dave

    • December 23, 2008 at 1:14 pm
      Permalink

      Problem solved! – I was doing two things wrong:

      Not specifying the content-type in my request:

      Request.ContentType = “text/xml”;

      The FBA login was redirecting, which I shouldn’t have followed. Doing the following fixed it:

      request.AllowAutoRedirect = false;

      Thanks

      Dave

    • January 9, 2009 at 2:20 am
      Permalink

      Very good stuff! Do you have the same for exchange 2007

      Best regards

      Thor

    • January 10, 2009 at 12:31 am
      Permalink

      Hello Thor!

      Basically you can use this code also with Exchange 2007 but you have to make some little changes.

      1. Exchange 2007 has different URL for authentication DLL.

      2. There is only one authentication cookie for Exchange 2007

    • February 17, 2009 at 11:21 am
      Permalink

      Hi,

      This solution works fine.However we need to give “password” in this case. In a case when we are using default credentials, can it be done without password?

    • March 17, 2009 at 6:37 pm
      Permalink

      Hi Gunnar,

      Thank you for posting this code. Are you able to offer me an example of how I might use your code to prevent the OWA login screen from appearing when a user clicks on a link to an inbox item? I am initially authenticating (successfully), passing a webDAV query, and returning & displaying the results on an .aspx (2.0) page. Within the results I have created anchor tags hyperlinked (using the exchange protocol format) to inbox items. However, when a user clicks on the item, the OWA login screen comes up. Specifically, how can I implement your code to bypass this screen?

      Thank you,

      Erik Snyder

    • March 18, 2009 at 11:07 am
      Permalink

      If you want it to be done easily then use Windows authentication. Browser takes care of everything. Otherwise… try to put these session cookies to user’s browser. See what happens.

    • June 20, 2009 at 12:44 pm
      Permalink

      Hi,

      Thanks for posting the code. But when tring to get the cookies we are getting 401 Unauthorized error. Could please let me know what could be the reason in getting 401 Unauthorized error?

      Thank You,

      KVL

    • August 18, 2009 at 6:19 pm
      Permalink

      error in Exchange 2007:

      details error:

      The remote certificate is invalid according to the validation procedure.

    • January 27, 2010 at 9:55 pm
      Permalink

      I know this is a very old post. But I going to try my luck anyway for an answer. I wrote a authenticate function based on your code.

      I am trying to connect to exchage 2007 , I keep getting bad request 400. I am not sure what i am doing wrong ,please help.

      My url’s work fine. and the username & password is right.

      public void authenticate()
      {
      string authURI = server + “/owa/auth/owaauth.dll”;
      // Create the web request body:
      string body = string.Format(“destination={0}&username={1}&password={2}”, server + path, username, password);
      byte[] bytes = Encoding.UTF8.GetBytes(body);

      // Create the web request:
      HttpWebRequest request = (HttpWebRequest)System.Net.WebRequest.Create(authURI);
      request.Method = “POST”;
      request.ContentType = “application/x-www-form-urlencoded”;
      request.CookieContainer = new CookieContainer();
      request.ContentLength = bytes.Length;
      request.UseDefaultCredentials = true;
      // Create the web request content stream:
      // request.KeepAlive = true;
      //request.AllowAutoRedirect = true;

      using (Stream stream = request.GetRequestStream())
      {
      stream.Write(bytes, 0, bytes.Length);
      stream.Close();
      }

      // Get the response & store the authentication cookies:
      HttpWebResponse response = (HttpWebResponse)request.GetResponse();

      if (response.Cookies.Count < 2)
      {
      Response.Write(“Login Failed”);
      //throw new AuthenticationException(“Login failed. Is the login / password correct?”);
      }
      else
      {
      CookieContainer cookies = new CookieContainer();
      foreach (Cookie myCookie in response.Cookies)
      {
      cookies.Add(myCookie);
      }
      }
      response.Close();

      }

    • January 28, 2010 at 10:02 am
      Permalink

      Just take fiddler2 and set it as proxy in your test machine. Now make all tasks you need to do in your code through OWA and save those requests and responses.

      Now make your application work exactly same way. Use fiddler2 to monitor requests that your application makes. You should get all work done pretty quickly this way.

    • October 21, 2010 at 11:47 am
      Permalink

      Can somebody put similar code for exchange 2010.

      What is the url for authentication dll, is this url (“/owa/auth.owa”) correct

    • October 21, 2010 at 12:31 pm
      Permalink

      Thanks for question, MadhuGowda! If you are lucky one with Exchange Server 2007 or 2010 you don’t have to use WebDAV protocol to communicate with Exchange Server. You can use web services and this is preferred way over WebDAV.

    • June 10, 2012 at 1:39 am
      Permalink

      Posting to the dll for owa no longer works in 2010, I have it working for 2007, does anyone know what they changed? I have been working on this for days with no resolve.

    Leave a Reply

    Your email address will not be published. Required fields are marked *