using System;
using System.Reflection;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
namespace Neo.Afx.Security
{
///
/// Allows for two-Level authentication with Forms Authentication and Windows Authentication in IIS 7.
///
/// See http://mvolo.com/blogs/serverside/archive/2008/02/11/IIS-7.0-Two_2D00_Level-Authentication-with-Forms-Authentication-and-Windows-Authentication.aspx
///
///
public class FormsAuthModule : IHttpModule
{
bool _enabled;
FormsAuthSettings _config;
FormsAuthenticationModule _module;
MethodInfo _onEnter;
MethodInfo _onLeave;
///////////////////////////////////////////////////////////////////////////////////////////////
// IHttpModule methods
///////////////////////////////////////////////////////////////////////////////////////////////
#region Dispose
///
/// Disposes of the resources (other than memory) used by the module that implements .
///
public void Dispose()
{
_module.Dispose();
_module = null;
GC.SuppressFinalize(this);
}
#endregion
#region Init
///
/// Initializes the object.
///
/// The current instance.
public void Init(HttpApplication app)
{
_module = new FormsAuthenticationModule();
using(var application = new HttpApplication())
{
_module.Init(application);
}
var type = _module.GetType();
_onEnter = type.GetMethod("OnEnter", BindingFlags.NonPublic | BindingFlags.Instance, null, new[]
{
typeof(object), typeof(EventArgs)
}, null);
_onLeave = type.GetMethod("OnLeave", BindingFlags.NonPublic | BindingFlags.Instance, null, new[]
{
typeof(object), typeof(EventArgs)
}, null);
if((_onEnter == null) || (_onLeave == null))
{
throw new Exception("Unable to get all required FormsAuthenticationModule entrypoints using reflection.");
}
app.AuthenticateRequest += OnAuthenticateRequest;
app.PostAuthenticateRequest += OnPostAuthenticateRequest;
app.EndRequest += OnEndRequest;
}
#endregion
///////////////////////////////////////////////////////////////////////////////////////////////
// Custom event handlers methods
///////////////////////////////////////////////////////////////////////////////////////////////
void OnAuthenticateRequest(object source, EventArgs e)
{
var application = (HttpApplication)source;
var context = application.Context;
_enabled = false;
_config = FormsAuthSettings.GetSection(context);
if(_config != null && _config.IsEnabled)
{
_enabled = true;
_onEnter.Invoke(_module, new[]
{
source, e
});
}
}
void OnEndRequest(object source, EventArgs e)
{
if(_enabled)
{
_onLeave.Invoke(_module, new[]
{
source, e
});
}
}
void OnPostAuthenticateRequest(object source, EventArgs e)
{
var application = (HttpApplication)source;
var context = application.Context;
if(!_enabled && context.User == null)
{
var logonUserIdentity = context.Request.LogonUserIdentity;
if(logonUserIdentity != null)
{
context.User = logonUserIdentity.IsAnonymous
? new WindowsPrincipal(WindowsIdentity.GetAnonymous())
: new WindowsPrincipal(logonUserIdentity);
}
}
}
}
}