We recently deployed our .net core app to a production environment, which is load-balanced. Users are reporting that the website dies at intermittent times -- usually after 20 - 30 minutes. The app can no longer get data from the database and the user is forced to log in again. It seems to happen most often during high traffic periods.
Prior to deployment, the app was tested on a load-balanced server and everything worked as expected.
Looking at the logs for the app, I see the following message:
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[7]
Cookies was not authenticated. Failure message: Unprotect ticket failed
I am thinking maybe something is wrong with how the data protection is set up. It currently uses a Database Context scheme.
Here is what the middleware looks like:
public void ConfigureServices(IServiceCollection services)
{
// Add a DbContext to store the Database Keys
services.AddDbContext<DatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DataProtection")));
// using Microsoft.AspNetCore.DataProtection;
services.AddDataProtection()
.PersistKeysToDbContext<DatabaseContext>();
services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
services.Configure<EnvironmentSettings>(options => Configuration.GetSection("EnvironmentSettings").Bind(options));
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.Secure = CookieSecurePolicy.SameAsRequest;
});
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
})
.AddCookie(cookieOptions =>
{
cookieOptions.AccessDeniedPath = "/AccessDenied";
cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(Convert.ToDouble(Configuration["wsfed:cookieTimeout"]));
cookieOptions.Cookie.SameSite = SameSiteMode.None;
cookieOptions.Cookie.Name = "FedAuth";
cookieOptions.Cookie.HttpOnly = true;
cookieOptions.Cookie.IsEssential = true;
})
.AddWsFederation(options =>
{
options.Wtrealm = Configuration["wsfed:realm"];
options.MetadataAddress = Configuration["wsfed:metadata"];
options.AllowUnsolicitedLogins = true;
options.CorrelationCookie.SameSite = SameSiteMode.None;
options.Events.OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.Wct = DateTimeOffset.UtcNow.ToString();
return Task.CompletedTask;
};
options.Events.OnSecurityTokenValidated += context =>
{
context.Properties.RedirectUri = Configuration["wsfed:redirecturi"];
return Task.CompletedTask;
};
options.Events.OnRemoteFailure += context =>
{
context.HandleResponse();
if (context.Failure.Message == "Correlation failed.")
{
context.Response.Redirect(Configuration["wsfed:realm"]);
}
return Task.CompletedTask;
};
});
Database Context Class:
public class DatabaseContext : DbContext, IDataProtectionKeyContext
{
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
Here are a list of things we tried so far:
- Checked DataProtectionKeys table in database for expired key. Everything looked ok.
- IIS: AppPool set idle timeout to 0, Start Mode to 'Always Running', Preload Enabled = True
- Tried to replicate issue in staging by turning off load-balancing while application was active. No problems witnessed, the app maintained connection to the database and continued working.
- Cleared cache to remove existing cookies
Any ideas on what could be wrong?
In my case the issue was that I was using the wrong crypto algorithm in my setup. I was using cookie authentication.
I had to change from SHA-1 to SHA-512 and the server was then able to "unprotect" (decrypt?) the auth cookie properly.