fix(security): make auth-cookie SecurePolicy configurable for HTTP-only deployments
The cookie SecurePolicy was hard-coded to Always, so the auth cookie was always marked Secure and the browser never sent it over plain HTTP — making login impossible on the HTTP-only Docker dev cluster (login succeeded server-side but every following request was unauthenticated). Add SecurityOptions.RequireHttps- Cookie (default true — production stays HTTPS-only); when false the cookie uses SameAsRequest. The docker/ central nodes set it false.
This commit is contained in:
@@ -30,7 +30,8 @@
|
|||||||
"LdapServiceAccountPassword": "password",
|
"LdapServiceAccountPassword": "password",
|
||||||
"JwtSigningKey": "scadalink-dev-jwt-signing-key-must-be-at-least-32-characters-long",
|
"JwtSigningKey": "scadalink-dev-jwt-signing-key-must-be-at-least-32-characters-long",
|
||||||
"JwtExpiryMinutes": 15,
|
"JwtExpiryMinutes": 15,
|
||||||
"IdleTimeoutMinutes": 30
|
"IdleTimeoutMinutes": 30,
|
||||||
|
"RequireHttpsCookie": false
|
||||||
},
|
},
|
||||||
"Communication": {
|
"Communication": {
|
||||||
"DeploymentTimeout": "00:02:00",
|
"DeploymentTimeout": "00:02:00",
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
"LdapServiceAccountPassword": "password",
|
"LdapServiceAccountPassword": "password",
|
||||||
"JwtSigningKey": "scadalink-dev-jwt-signing-key-must-be-at-least-32-characters-long",
|
"JwtSigningKey": "scadalink-dev-jwt-signing-key-must-be-at-least-32-characters-long",
|
||||||
"JwtExpiryMinutes": 15,
|
"JwtExpiryMinutes": 15,
|
||||||
"IdleTimeoutMinutes": 30
|
"IdleTimeoutMinutes": 30,
|
||||||
|
"RequireHttpsCookie": false
|
||||||
},
|
},
|
||||||
"Communication": {
|
"Communication": {
|
||||||
"DeploymentTimeout": "00:02:00",
|
"DeploymentTimeout": "00:02:00",
|
||||||
|
|||||||
@@ -92,4 +92,14 @@ public class SecurityOptions
|
|||||||
/// Minutes before token expiry to trigger refresh.
|
/// Minutes before token expiry to trigger refresh.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int JwtRefreshThresholdMinutes { get; set; } = 5;
|
public int JwtRefreshThresholdMinutes { get; set; } = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When true (default) the authentication cookie is always marked
|
||||||
|
/// <c>Secure</c> (sent only over HTTPS) — the correct production setting,
|
||||||
|
/// since the cookie carries the embedded JWT bearer credential. Set false
|
||||||
|
/// for an HTTP-only deployment such as the local Docker dev cluster: the
|
||||||
|
/// cookie then uses <c>SameAsRequest</c>, so it is still <c>Secure</c> on
|
||||||
|
/// any HTTPS request but is usable over plain HTTP.
|
||||||
|
/// </summary>
|
||||||
|
public bool RequireHttpsCookie { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ public static class ServiceCollectionExtensions
|
|||||||
options.Cookie.Name = "ScadaLink.Auth";
|
options.Cookie.Name = "ScadaLink.Auth";
|
||||||
options.Cookie.HttpOnly = true;
|
options.Cookie.HttpOnly = true;
|
||||||
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
|
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
|
||||||
// The cookie carries the embedded JWT (a bearer credential); never
|
// Cookie.SecurePolicy is set in the PostConfigure block below so it
|
||||||
// transmit it over plain HTTP. Design: "HttpOnly and Secure (requires HTTPS)".
|
// can honour SecurityOptions.RequireHttpsCookie.
|
||||||
options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// CentralUI-005: configure the cookie session as a sliding window so the
|
// CentralUI-005: configure the cookie session as a sliding window so the
|
||||||
@@ -46,6 +45,14 @@ public static class ServiceCollectionExtensions
|
|||||||
var idleMinutes = securityOptions.Value.IdleTimeoutMinutes;
|
var idleMinutes = securityOptions.Value.IdleTimeoutMinutes;
|
||||||
cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(idleMinutes);
|
cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(idleMinutes);
|
||||||
cookieOptions.SlidingExpiration = true;
|
cookieOptions.SlidingExpiration = true;
|
||||||
|
|
||||||
|
// The cookie carries the embedded JWT bearer credential. Production
|
||||||
|
// keeps it HTTPS-only (Always); an HTTP-only deployment (e.g. the
|
||||||
|
// local Docker dev cluster) opts out via RequireHttpsCookie=false and
|
||||||
|
// uses SameAsRequest — still Secure on any HTTPS request.
|
||||||
|
cookieOptions.Cookie.SecurePolicy = securityOptions.Value.RequireHttpsCookie
|
||||||
|
? Microsoft.AspNetCore.Http.CookieSecurePolicy.Always
|
||||||
|
: Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest;
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddScadaLinkAuthorization();
|
services.AddScadaLinkAuthorization();
|
||||||
|
|||||||
Reference in New Issue
Block a user