diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index 4d897f5..d7e2d58 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -596,7 +596,8 @@ namespace CarCareTracker.Controllers ReminderUrgencyConfig = _config.GetReminderUrgencyConfig(), EnableAuth = _config.GetServerAuthEnabled(), DefaultReminderEmail = _config.GetDefaultReminderEmail(), - EnableRootUserOIDC = _config.GetEnableRootUserOIDC() + EnableRootUserOIDC = _config.GetEnableRootUserOIDC(), + CookieLifeSpan = _config.GetAuthCookieLifeSpan().ToString() }; return View(viewModel); } diff --git a/Controllers/LoginController.cs b/Controllers/LoginController.cs index 81de884..1ab2312 100644 --- a/Controllers/LoginController.cs +++ b/Controllers/LoginController.cs @@ -185,7 +185,7 @@ namespace CarCareTracker.Controllers }; var serializedCookie = JsonSerializer.Serialize(authCookie); var encryptedCookie = _dataProtector.Protect(serializedCookie); - Response.Cookies.Append("ACCESS_TOKEN", encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) }); + Response.Cookies.Append(StaticHelper.LoginCookieName, encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) }); return new RedirectResult("/Home"); } else { @@ -353,11 +353,11 @@ namespace CarCareTracker.Controllers AuthCookie authCookie = new AuthCookie { UserData = userData, - ExpiresOn = DateTime.Now.AddDays(credentials.IsPersistent ? 30 : 1) + ExpiresOn = DateTime.Now.AddDays(credentials.IsPersistent ? _config.GetAuthCookieLifeSpan() : 1) }; var serializedCookie = JsonSerializer.Serialize(authCookie); var encryptedCookie = _dataProtector.Protect(serializedCookie); - Response.Cookies.Append("ACCESS_TOKEN", encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) }); + Response.Cookies.Append(StaticHelper.LoginCookieName, encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) }); return Json(true); } } @@ -390,7 +390,7 @@ namespace CarCareTracker.Controllers }; var serializedCookie = JsonSerializer.Serialize(authCookie); var encryptedCookie = _dataProtector.Protect(serializedCookie); - Response.Cookies.Append("ACCESS_TOKEN", encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) }); + Response.Cookies.Append(StaticHelper.LoginCookieName, encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) }); } } return Json(result); @@ -438,7 +438,7 @@ namespace CarCareTracker.Controllers //destroy any login cookies. if (result) { - Response.Cookies.Delete("ACCESS_TOKEN"); + Response.Cookies.Delete(StaticHelper.LoginCookieName); } return Json(result); } @@ -452,7 +452,7 @@ namespace CarCareTracker.Controllers [HttpPost] public IActionResult LogOut() { - Response.Cookies.Delete("ACCESS_TOKEN"); + Response.Cookies.Delete(StaticHelper.LoginCookieName); var remoteAuthConfig = _config.GetOpenIDConfig(); if (remoteAuthConfig.DisableRegularLogin && !string.IsNullOrWhiteSpace(remoteAuthConfig.LogOutURL)) { diff --git a/Helper/ConfigHelper.cs b/Helper/ConfigHelper.cs index e3e87d7..1436f5d 100644 --- a/Helper/ConfigHelper.cs +++ b/Helper/ConfigHelper.cs @@ -35,6 +35,7 @@ namespace CarCareTracker.Helper bool GetInvariantApi(); bool GetServerOpenRegistration(); string GetDefaultReminderEmail(); + int GetAuthCookieLifeSpan(); } public class ConfigHelper : IConfigHelper { @@ -89,6 +90,26 @@ namespace CarCareTracker.Helper { return CheckBool(CheckString("LUBELOGGER_OPEN_REGISTRATION")); } + public int GetAuthCookieLifeSpan() + { + var lifespan = CheckString("LUBELOGGER_COOKIE_LIFESPAN", StaticHelper.DefaultCookieLifeSpan); + if (!string.IsNullOrWhiteSpace(lifespan) && int.TryParse(lifespan, out int lifespandays)) + { + if (lifespandays > 90) //max 90 days because that is the max lifetime of the DPAPI keys + { + lifespandays = 90; + } + if (lifespandays < 1) //min 1 day because cookie lifespan is incremented in days for our implementation + { + lifespandays = 1; + } + return lifespandays; + } + else + { + return int.Parse(StaticHelper.DefaultCookieLifeSpan); //default is 30 days for when remember me is selected. + } + } public bool GetServerAuthEnabled() { return CheckBool(CheckString(nameof(UserConfig.EnableAuth))); @@ -244,6 +265,10 @@ namespace CarCareTracker.Helper { serverConfig.EnableRootUserOIDC = null; } + if (serverConfig.CookieLifeSpan == StaticHelper.DefaultCookieLifeSpan || string.IsNullOrWhiteSpace(serverConfig.CookieLifeSpan)) + { + serverConfig.CookieLifeSpan = null; + } try { File.WriteAllText(StaticHelper.ServerConfigPath, JsonSerializer.Serialize(serverConfig)); diff --git a/Helper/StaticHelper.cs b/Helper/StaticHelper.cs index 7093ac7..372e4be 100644 --- a/Helper/StaticHelper.cs +++ b/Helper/StaticHelper.cs @@ -29,6 +29,8 @@ namespace CarCareTracker.Helper public const string ReleasePath = "https://api.github.com/repos/hargata/lubelog/releases/latest"; public const string TranslationDirectoryPath = $"{TranslationPath}/directory.json"; public const string ReportNote = "Report generated by LubeLogger, a Free and Open Source Vehicle Maintenance Tracker - LubeLogger.com"; + public const string LoginCookieName = "ACCESS_TOKEN"; + public const string DefaultCookieLifeSpan = "30"; public static string GetTitleCaseReminderUrgency(ReminderUrgency input) { switch (input) diff --git a/Middleware/Authen.cs b/Middleware/Authen.cs index 32e86ab..36e4881 100644 --- a/Middleware/Authen.cs +++ b/Middleware/Authen.cs @@ -1,4 +1,5 @@ -using CarCareTracker.Logic; +using CarCareTracker.Helper; +using CarCareTracker.Logic; using CarCareTracker.Models; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.DataProtection; @@ -49,7 +50,7 @@ namespace CarCareTracker.Middleware else { //auth is enabled by user, we will have to authenticate the user via a ticket retrieved from the auth cookie. - var access_token = _httpContext.HttpContext.Request.Cookies["ACCESS_TOKEN"]; + var access_token = _httpContext.HttpContext.Request.Cookies[StaticHelper.LoginCookieName]; //auth using Basic Auth for API. var request_header = _httpContext.HttpContext.Request.Headers["Authorization"]; if (string.IsNullOrWhiteSpace(access_token) && string.IsNullOrWhiteSpace(request_header)) diff --git a/Models/ServerConfig.cs b/Models/ServerConfig.cs index dbe9cfd..6b6dd22 100644 --- a/Models/ServerConfig.cs +++ b/Models/ServerConfig.cs @@ -74,5 +74,8 @@ namespace CarCareTracker.Models [JsonPropertyName("LUBELOGGER_LOCALE_DT_OVERRIDE")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? LocaleDateTimeOverride { get; set; } = string.Empty; + [JsonPropertyName("LUBELOGGER_COOKIE_LIFESPAN")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? CookieLifeSpan { get; set; } = string.Empty; } } \ No newline at end of file diff --git a/Models/Settings/ServerSettingsViewModel.cs b/Models/Settings/ServerSettingsViewModel.cs index 47974d3..275cd08 100644 --- a/Models/Settings/ServerSettingsViewModel.cs +++ b/Models/Settings/ServerSettingsViewModel.cs @@ -22,5 +22,6 @@ namespace CarCareTracker.Models public bool EnableRootUserOIDC { get; set; } public bool EnableAuth { get; set; } public List AvailableLocales { get; set; } + public string CookieLifeSpan { get; set; } } }