I have solved this exact problem. In the following manner:
web.config
:
<authentication mode="Forms">
<forms name="APPAUTH"
defaultUrl="/webapp/Home.mvc"
loginUrl="/webapp/Session.mvc/Login"
protection="All"
timeout="30"
path="/"/>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
<location path="Session">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
Then I hook Application_AuthenticateRequest
something along the lines of:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (null == authCookie)
{
//no authentication cokie present
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch (Exception)
{
// Can't do anything if we can't decrypt the ticket so treat it as not there
FormsAuthentication.SignOut(); // Remove bad ticket
}
if (authTicket == null)
{
//could not decrypt cookie
return;
}
// get the role
string[] roles = authTicket.UserData.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
// Set the security context
ISecurityService security = ContainerProvider.RequestContainer.Resolve<ISecurityService>();
Models.User user = security.GetUser(authTicket.Name);
if (user == null)
{
FormsAuthentication.SignOut();
throw new HttpException((int)System.Net.HttpStatusCode.Unauthorized, "Session expired!");
}
AppIdentity id = new AppIdentity(user, !authTicket.Expired);
AppPrincipal principal = new AppPrincipal(id, roles);
Context.User = principal;
}
The ContainerProvider.RequestContainer.Resolve<ISecurityService>();
call is to a Autofac container, but you can do anything you need to / want to here.
The AppIdentity
and AppPrincipal
classes are custom so I can access my roles, but they are not that complicated.