Answered by:
Cookie Authentication in Docker Container in Linux - Cookie is invalidated on each deployment

Question
-
User-451260051 posted
I have an .NET Core 2.2 MVC app that I'm deploying via Docker in a Linux environment. I'm using cookie authentication, which is working great except when a new deployment happens. It seems the cookie is invalidated on each new container. Here is what I've implemented so far, based on blog posts around the web, but I cannot get this to work correctly.
- I created a new PFX certificate and included it in the container via a COPY command in the Dockerfile:
... COPY ./resources/certificate.pfx ./etc/keys/certificate.pfx ...
- In my ConfigureServices method in Startup.cs I've enabled DataProtection using the certificate:
services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo("../etc/keys/")) .ProtectKeysWithCertificate(this.CreateOauthCertificate()) .SetApplicationName("MYAPP");
private X509Certificate2 CreateOauthCertificate() { var path = "../etc/keys/certificate.pfx"; var password = "MYPASSWORD"; return new X509Certificate2(path, password); }
- Then I configure cookie authentication:
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; }); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = "/auth/signin"; options.LogoutPath = "/auth/signout"; options.Cookie.Name = ".AspNet.SharedCookie"; });
That's it, I deploy the container and log in just fine until the next deployment, then everyone has to log in again. I've gone down this path as I read that if DataProtection is not in place with a custom certificate then each container will encrypt the cookie differently, which makes sense.
Any help is appreciated! Thank you!
Wednesday, August 7, 2019 10:40 AM - I created a new PFX certificate and included it in the container via a COPY command in the Dockerfile:
Answers
-
User-474980206 posted
by default, the keys are generated on each startup (max security). you can persist the keys to storage, to use the same keys on a recycle. if you want to share keys between a load balanced, or shared sites, they must use the same storage location. Your code was persisting between recycles, but not deployments (because the storage was deleted on deployment).
see:
https://docs.microsoft.com/en-us/aspnet/core/security/cookie-sharing?view=aspnetcore-2.2
note: the default hosting settings, the cookie lasts 20 minutes, and the site goes idle (shuts down) after 20 minutes. this means on a startup after idle, there are no valid cookies, so new keys can be used.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Wednesday, August 7, 2019 10:31 PM
All replies
-
User-474980206 posted
when you create a new docker container, all filesystem data is lost. you should create a storage only container to hold the key data. this storage container should be mounted in the new container, and used as the storage of the persisted keys and any other file data you want to persist between deployments. you could just mount a local filesystem instead of a container.
Wednesday, August 7, 2019 2:13 PM -
User-451260051 posted
Hey Bruce, thanks for the reply. I guess I'm just curious as to why I need to store anything? My thought process was the cookie is being created/encrypted with the PFX certificate included in the container. As such I would expect it to to work fine if the same certificate is there. But based on your answer, it sounds like key data is being generated and stored in the container, and that is being used to encrypt the cookie?
Wednesday, August 7, 2019 6:21 PM -
User-474980206 posted
by default, the keys are generated on each startup (max security). you can persist the keys to storage, to use the same keys on a recycle. if you want to share keys between a load balanced, or shared sites, they must use the same storage location. Your code was persisting between recycles, but not deployments (because the storage was deleted on deployment).
see:
https://docs.microsoft.com/en-us/aspnet/core/security/cookie-sharing?view=aspnetcore-2.2
note: the default hosting settings, the cookie lasts 20 minutes, and the site goes idle (shuts down) after 20 minutes. this means on a startup after idle, there are no valid cookies, so new keys can be used.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Wednesday, August 7, 2019 10:31 PM -
User-451260051 posted
Dang, I had read both of those but never scrolled far enough down on the Data Protection page to find this: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-2.2#persisting-keys-when-hosting-in-a-docker-container
It says exactly what you are talking about. Bummer! Ok, looks like I'm using Redis then. https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/implementation/key-storage-providers?view=aspnetcore-2.2&tabs=visual-studio#redis
Thanks!
Thursday, August 8, 2019 1:02 AM -
User1520731567 posted
Hi tehremo,
For this kind of topic,I suggest you could move to ASP.NET Core to get more help and a deeper understanding.
Best Regards.
Yuki Tao
Thursday, August 8, 2019 9:39 AM