After apparently successfully running the following on a login page: var result = signinManager.PasswordSignIn(Username.Text, Password.Text, RememberMe.Checked, shouldLockout: false);
On the next page I check for: if (HttpContext.Current.User.Identity.IsAuthenticated) ...
Which is usually true. However, when the browser cache is forcibly cleared, the user is forwarded to the login page as usual, and the signManager result seems to be 'SignInStatus.Success', however the IsAuthenticated on the next page is now false. Basically the user cannot then log in at all, and there are no error messages.
The same effect appears to happen once the cookie has expired(?). There seems no way of reauthenticating the user, unless I recycle the site/app pool.
Background
I'm using the Visual Studio 2013 ASP.NET WebApplication project template (Web Forms), and choosing the 'individual user accounts' authentication option. I am then following the basic approach of this project: Getting Started with ASP.NET 4.5 Web Forms and Visual Studio 2013
To set up the entities etc. I am finding that, when using SQL Server as a datastore, the above issue arises, either when the authentication expires, or you forcibly clear the browser cache. I have tried updatind the to latest Entity Framework (6.1.3 at time of writing, using ASP.NET Identity 2.2.1), changing the sql express version, and updating all other libraries I could find. But the same issue prevails. It must be me, coming from a Forms Membership coding background - most grateful for any help as I'm completely stuck.
Any Relevent Code:
protected void LogIn(object sender, EventArgs e)
{
if (IsValid)
{
// Validate the user password
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();
var user = manager.FindByName(Username.Text);
var result = signinManager.PasswordSignIn(Username.Text, Password.Text, RememberMe.Checked, shouldLockout: false);
// If username and password is correct check if account is activated.
if (result == SignInStatus.Success)
{
if (!user.EmailConfirmed && result == SignInStatus.Success)
{
FailureText.Text = "Invalid login attempt. You must have a confirmed email account.";
ErrorMessage.Visible = true;
return;
}
}
switch (result)
{
case SignInStatus.Success:
dentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
Response.Redirect("/Account/Lockout");
break;
case SignInStatus.RequiresVerification:
Response.Redirect(String.Format("/Account/TwoFactorAuthenticationSignIn?ReturnUrl={0}&RememberMe={1}",
Request.QueryString["ReturnUrl"],
RememberMe.Checked),
true);
break;
case SignInStatus.Failure:
default:
FailureText.Text = "Invalid login attempt";
ErrorMessage.Visible = true;
break;
}
}
}
On the page the above redirects to:
protected override void OnLoad(EventArgs e)
{
int test = Session.Timeout;
System.Security.Principal.IPrincipal usr1 = this.Page.User;
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindById(User.Identity.GetUserId());
bool redirectToLogIn = true;
if (user != null) //is null when we have the problem
{
var identity = manager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
if (identity.IsAuthenticated)
{
if ((User.IsInRole("administrator") || (User.IsInRole("manager"))))
{
redirectToLogIn = false;
}
}
}
if (HttpContext.Current.User.Identity.IsAuthenticated) //is false when we have the problem
{
System.Security.Principal.IPrincipal usr = this.Page.User;
if ((usr.IsInRole("administrator") || (usr.IsInRole("manager"))))
{
redirectToLogIn = false;
}
}
if (redirectToLogIn)
{
Response.Redirect("~/Account/Login/?ReturnUrl=" + HttpUtility.UrlEncode(localTheRetUrl));
}
...
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
//Added by me
OnException = (context =>
{
//throw context.Exception;
})
},
ExpireTimeSpan = TimeSpan.FromMinutes(5) //For Testing
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = false,
};
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) :
base(userManager, authenticationManager) { }
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
}
}