static void

Basic Authentication HttpModule

An HttpModule using PostAuthenticateRequest so that Basic Authentication works in a site that is otherwise Forms authenticated.

HttpModule

Static initialized with an IAuthenticationService which takes username/password and returns an IPrincipal.

using System;
using System.Diagnostics;
using System.Net;
using System.Security;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
 
namespace WebApplication1
{
    public class BasicAuthenticationHttpModule : IHttpModule
    {
        private static IAuthenticationService _authenticationService;
        public static void SetBasicAuthenticationValidator(IAuthenticationService authenticationService)
        {
            _authenticationService = authenticationService;
        }
 
        public void Init(HttpApplication context)
        {
            context.PostAuthenticateRequest += ContextOnAuthenticateRequest;
        }
 
        private static void ContextOnAuthenticateRequest(object sender, EventArgs eventArgs)
        {
            if (_authenticationService == null ||
                HttpContext.Current == null ||
                HttpContext.Current.User == null ||
                HttpContext.Current.User.Identity.IsAuthenticated)
                return;
            try
            {
                IPrincipal principal = null;
                var headers = HttpContext.Current.Request.Headers;
                var authValue = headers[HttpRequestHeader.Authorization.ToString()];
                //if no Basic header, don't prompt for it
                if (authValue == null ||
                    string.IsNullOrWhiteSpace(authValue) ||
                    !authValue.StartsWith("Basic"))
                {
                    return;
                }
                //try to parse for it
                var parsedCredentials = ParseAuthorizationHeader(authValue);
                if (parsedCredentials != null)
                {
                    principal = _authenticationService.ValidateCredentials(
                        parsedCredentials.Item1, parsedCredentials.Item2);
                }
 
                if (principal == null)
                {
                    Unauthorized(HttpContext.Current);
                    return;
                }
                SetPrincipal(principal);
            }
            catch (SecurityException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new SecurityException("Unexpected error. See inner exception for details.", ex);
            }
        }
 
        private static void Unauthorized(HttpContext context)
        {
            Trace.TraceWarning("Unauthorized basic credentials");
            context.Response.Headers.Add("WWW-Authenticate", "Basic");
            context.Response.StatusCode = 401;
            context.Response.StatusDescription = "Invalid credentials";
            context.ApplicationInstance.CompleteRequest();
        }
 
        private static Tuple<string, string> ParseAuthorizationHeader(string authHeader)
        {
            try
            {
                string base64Credentials = authHeader.Substring(6);
                var credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials))
                                          .Split(new[] { ':' });
                if (credentials.Length != 2 ||
                    string.IsNullOrEmpty(credentials[0]) ||
                    string.IsNullOrEmpty(credentials[1]))
                {
                    return null;
                }
 
                return new Tuple<string, string>(credentials[0], credentials[1]);
            }
            catch (Exception exception)
            {
                Trace.TraceError("BasicAuthentication: ParseHeader " + exception);
                throw;
            }
        }
 
 
        private static void SetPrincipal(IPrincipal principal)
        {
            Thread.CurrentPrincipal = principal;
            HttpContext.Current.User = Thread.CurrentPrincipal;
        }
 
        public void Dispose()
        {
        }
    }
}

Registration

<system.webServer>
  <modules>
    <add name="BasicAuthenticationHttpModule" type="WebApplication1.BasicAuthenticationHttpModule" />
  </modules>
</system.webServer>

Global.asax

void Application_Start(object sender, EventArgs e)
{
    BasicAuthenticationHttpModule.SetBasicAuthenticationValidator(new AuthenticationService());
}

Async

If AuthenticationService is async, in .net 4.5 you can:

public void Init(HttpApplication context)
{
    var asyncHelper = new EventHandlerTaskAsyncHelper(ContextOnAuthenticateRequest);
    context.AddOnPostAuthenticateRequestAsync(asyncHelper.BeginEventHandler, asyncHelper.EndEventHandler);
}
 
private static async Task ContextOnAuthenticateRequest(object sender, EventArgs eventArgs)
{