none
OWA Custom Authentication RRS feed

  • Question

  • Hello,

    I am attempting to develop an IIS Authentication Module using C# code (testing on Windows SBS 2011).

    The sole purpose of the module is to perform authentication using a custom HTTP header.

    Based on the contents of this custom header, a user is authenticated by creating a Principal and assigning it to the "User" attribute of the current HttpContext.

    My current code actually works perfectly fine against a helloworld-type test web app : I send a HTTP request using the previously-mentioned custom HTTP Header, the module produces a Principal and the webapp can access it through System.Web.HttpContext.Current.User.Identity.Name and System.Web.HttpContext.Current.User.Identity.IsAuthenticated (which returns true).

    Surprisingly, when using the same module for Outlook Web Access (OWA), an error is reported by OWA in the web page : "Outlook Web App didn't initialize. If the problem continues, please contact your helpdesk.", with no additional information. Windows event viewer on the server shows no message relating to this.

    Information about the code

    Initialization is very simple, I just attach my methods to the "AuthenticateRequest" and "EndRequest" events:

            // Init (IHttpModule Implementation)
            public void Init(HttpApplication ctx)
            {
                // Register Events
                ctx.AuthenticateRequest += new EventHandler(this.Authenticate);
                ctx.EndRequest += new EventHandler(this.IssueAuthChallenge);
            }

    The code for the authenticate  method is as follows :

    // Authenticate User public void Authenticate(Object src, EventArgs e) { // Acquire Source and Context HttpApplication app = (HttpApplication)src; HttpContext ctx = app.Context; // Acquire Client Certificate HttpClientCertificate client_cert = ctx.Request.ClientCertificate; String client_cn = client_cert.Get(ClientCert_SubjectCN); // Acquire Authentication Headers String username = ctx.Request.Headers[HttpHeader_AuthUsername]; // Drop Invalid Requests if((username == null) || (!(client_cert.IsPresent))) { return; } // Check Client Certificate CN if(client_cn != AllowedClientCN) { return; } // Check Group Membership if(!(AD.isMemberOf(ActiveDirectoryDomain, username, AuthGroup))) { return; } // Authentication Passed - Register User Principal

    IPrincipal principal = new GenericPrincipal(new GenericIdentity(username), new String[] { AuthGroup });

    HttpContext.Current.User = principal;
                ctx.User = principal;
                Thread.CurrentPrincipal = principal;

    }

    EndRequest event is handled as follows :

            // Issue Auth Challenge
            public void IssueAuthChallenge(Object src, EventArgs e)
            {
                // Acquire Source and Context
                HttpApplication app = (HttpApplication)src;
                HttpContext ctx = app.Context;
    
                // Issue Authentication Header
                ctx.Response.AddHeader(HttpHeader_AuthRequired, "Authentication Required");
    
                // Drop WWW-Authenticate Header
                ctx.Response.Headers.Remove(HttpHeader_WWWAuthenticate);
    
                // Redirect to Authentication Area
                ctx.Response.StatusCode = HttpStatusCode_Found;
                ctx.Response.AddHeader(HttpHeader_Location, AuthLocation);
            }

    Finally, here are the global definitions referenced throughout the code :

            // Active Directory Domain
            public const String ActiveDirectoryDomain = "FOODOM";
    
            // Allowed Client CN (Reverse-Proxy)
            public const String AllowedClientCN = "FooCertName";
    
            // Authentication Authorized Group
            public const String AuthGroup = "FooAuthAllowed";
    
            // Authentication Custom HTTP Header Base
            public const String HttpHeader_AuthBase = "X-FooAuth";
    
            // HTTP WWW-Authenticate Header
            public const String HttpHeader_WWWAuthenticate = "WWW-Authenticate";
    
            // HTTP Location Header
            public const String HttpHeader_Location = "Location";
    
            // Client Certificate Fields
            public const String ClientCert_SubjectCN = "SUBJECTCN";
    
            // Authentication Custom HTTP Headers
            public const String HttpHeader_AuthRequired = HttpHeader_AuthBase + "-Required";
            public const String HttpHeader_AuthUsername = HttpHeader_AuthBase + "-Username";
    
            // HTTP Status Codes
            public const int HttpStatusCode_NotAuthorized = 401;
            public const int HttpStatusCode_Found = 302;
    
            // Authentication Area
            public const String AuthLocation = "/FooAuth";

    After spending many hours fiddling with the IIS settings (mostly authentication and SSL options) I simply do not understand why OWA throws an error when my test app works fine. Are there any specifics that need to be performed to allow OWA to authenticate ?




    • Edited by Void.Ptr Monday, July 20, 2015 9:51 AM
    Monday, July 20, 2015 8:51 AM

All replies