I am attempting to re-do a login system using Claims-Based auth.
So far, so good
Stepping through, it appears to correctly evaluate a username and password and correctly create a claims principal (including adding an authentication type in order to set IsAuthenticated to true, per this SO question.)
But then...
Somehow the identity doesn't seem to correctly get set on the wire. As a result, I'm redirected directly back to the login page.
The Code
I have the following in global.asax
:
private void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
var currentPrincipal = ClaimsPrincipal.Current;
var transformer = new ClaimsTransformer(); //My own custom transformer; code below.
var newPrincipal = transformer.Authenticate(string.Empty, currentPrincipal); // does the transformation
// as I understand, it is proper & recommnded to set both of these
Thread.CurrentPrincipal = newPrincipal;
HttpContext.Current.User = newPrincipal;
}
In my Login Controller, I have a simple test against a membership DB. I verified while debugging that this has newCP
as a valid, authenticated identity that has the expected name.
[HttpPost]
[AllowAnonymous]
public ActionResult UserLogin(LoginViewModel viewModel)
{
var loginSuccess = Membership.ValidateUser(viewModel.UserName, viewModel.Password);
if (loginSuccess)
{
// CustomApplicationIdentity puts some identity-based logic into business domain terms and uses Claims underneath.
//Should have done it at the IPrincipal level, but instead I created the ToAuthenticatedStandardClaimsIdentity() which returns a new authenticated ClaimsIdentity.
var newIdentity = new CustomApplicationIdentity(viewModel.UserName);
var cp = new ClaimsPrincipal(newIdentity.ToAuthenticatedStandardClaimsIdentity());
var newCP = new ClaimsTransformer().Authenticate(string.Empty, cp);
System.Web.HttpContext.Current.User = newCP;
Thread.CurrentPrincipal = newCP;
if (!string.IsNullOrWhiteSpace(viewModel.ReturnUrl))
{
return Redirect(viewModel.ReturnUrl);
}
return RedirectToAction("Index", "Identity");
}
}
The Problem
When it redirects to the Action, I see it hit the Application_PostAuthenticateRequest
again, which makes perfect sense.
However, despite previously setting the principal, this now appears to be an empty principal (no name, with IsAuthenticated set to false).
Where am I Going Wrong?
Some thoughts:
- Is it because I haven't set up the SessionSecurityToken yet?
- Am I completely missing something regarding threading or setting the context correctly?
- Since the UserLogin method is in MVC, I also tried using controller context, but that didn't seem to work either.
- Is it possible that something else could be messing with this in the middle?
- Read: Is there an easy way to verify that some portion of the old login system isn't left over and toying with me?