The Problem
I've got an ASP.NET site that when I initially deployed the site worked perfectly in regards to sign-in/sign-out. When I re-deploy new changes (via replacing files) those who are logged in (have cookies) are no longer recognized as logged in. Furthermore, they're not able to login as clicking login takes them the azure login, then it redirects back to the home page and doesn't detect the cookie so it shows them still logged out.
None of these things happen in Visual Studio and IIS Express only when I deploy to QA (IIS 6.2).
Relevant Code
AccountController
[AllowAnonymous]
public void SignIn()
{
if (Request.IsAuthenticated) { return; }
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties() { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType
);
}
public void SignOut()
{
if (!Request.IsAuthenticated) { return; }
// SIGN OUT:
HttpContext.GetOwinContext().Authentication.SignOut(
OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType
);
// COOKIE: Remove the cookie.
var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
cookie.Expires = DateTime.UtcNow.AddDays(-1);
Response.Cookies.Add(cookie);
}
AzureSettings ran from Startup.cs
public static void ConfigureAzure(IAppBuilder app)
{
// COOKIES: Tells it to use cookies for authentication.
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
// CUSTOMIZE: This is where you would adjust cookie experiation and things of that nature.
});
//https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-webapp-webapi-openidconnect/
// OPEN-ID: Handle OpenID stuff.
var notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = PrincipalService.OnAzureAuthenticationFailure,
// REFERENCE: https://russellyoung.net/2015/09/05/mvc-role-based-authorization-with-azure-active-directory-aad/
AuthorizationCodeReceived = PrincipalService.OnAzureAuthenticationSuccess
};
var options = new OpenIdConnectAuthenticationOptions()
{
ClientId = ClientID,
Authority = Authority,
PostLogoutRedirectUri = PostLogoutRedirectUri,
Notifications = notifications
};
app.UseOpenIdConnectAuthentication(options);
}
PrincipalService.cs referenced in the code above
/// <summary>
/// Redirects the user to the /Home/ErrorInfo page.
/// </summary>
public static Task OnAzureAuthenticationFailure(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
context.HandleResponse();
context.Response.Redirect("/Home/ErrorInfo");
return Task.FromResult(0);
}
/// <summary>
/// Stores the proper identity cookie (doesn't have customer permissions yet).
/// </summary>
public static Task OnAzureAuthenticationSuccess(AuthorizationCodeReceivedNotification context)
{
var username = context.AuthenticationTicket.Identity.Name;
try
{
StoreCookie(username);
}
catch (DbEntityValidationException ex)
{
var errors = ex.EntityValidationErrors.FirstOrDefault()?.ValidationErrors.FirstOrDefault()?.ErrorMessage;
Logger.Log(Level.Error, "An error occurred while storing authentication cookie.", ex);
}
catch (Exception ex)
{
Logger.Log(Level.Error, "An error occurred while storing authentication cookie.", ex);
}
return Task.FromResult(0);
}
/// <summary>
/// Creates and stores a forms authentication cookie for the user.
/// </summary>
private static void StoreCookie(string username, bool rememberMe = false)
{
Logger.Log(Level.Info, "Storing Cookie");
var azureUsers = new AzureUserRepository(new AuthenticationEntities());
var user = azureUsers.Get(u => u.Username == username);
if (user == null)
{
throw new NullReferenceException();
}
// Clear any old existing cookies.
HttpContext.Current.Request.RemoveFormsAuthCookie();
// Create the principal from the user object.
var principal = new PrincipalModel(user);
// Create and store the cookie in the response.
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] {
new ActivityConverter(),
new RoleConverter(),
new PrincipalModelConverter()
});
HttpContext.Current.Response.AddFormsAuthCookie(
username: user.Username,
userData: serializer.Serialize(principal),
isPersistent: rememberMe
);
}
Summary
- Redeploying the site to QA causes users that were still logged in to no longer be recognized by the server as logged in (therefore showing the login link).
- Afterwards, clicking sign-in takes them to azure login and then redirects them to the home page where they're not recognized as signed-in.
- Deleting the page's cookies in Chrome fixes this until the next time it happens.
- This doesn't happen while developing (Visual Studio and IIS Express) only when I deploy to QA's IIS 6.2 (We don't have a production server yet).
What am I doing to cause this? What needs done to prevent this from happening?