feat(dashboard): swap to auto-login handler when DisableLogin is set
This commit is contained in:
@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.Auth.Abstractions.Roles;
|
||||
using ZB.MOM.WW.Auth.AspNetCore;
|
||||
@@ -55,9 +56,36 @@ public static class DashboardServiceCollectionExtensions
|
||||
.AddInteractiveServerComponents();
|
||||
services.AddSignalR();
|
||||
|
||||
services
|
||||
.AddAuthentication(DashboardAuthenticationDefaults.AuthenticationScheme)
|
||||
.AddCookie(DashboardAuthenticationDefaults.AuthenticationScheme, cookieOptions =>
|
||||
// DEV/TEST ONLY. Read directly from configuration here because authentication scheme
|
||||
// registration runs before options binding. Key mirrors DashboardOptions.DisableLogin.
|
||||
bool disableLogin = configuration.GetValue<bool>("MxGateway:Dashboard:DisableLogin");
|
||||
|
||||
AuthenticationBuilder authentication =
|
||||
services.AddAuthentication(DashboardAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
if (disableLogin)
|
||||
{
|
||||
// Register an always-authenticating handler UNDER the cookie scheme name, so the
|
||||
// Viewer/Admin/HubClients policies (which all resolve this scheme) authenticate
|
||||
// through it as the multi-role dev user — zero policy or page changes.
|
||||
authentication.AddScheme<AuthenticationSchemeOptions, DashboardAutoLoginAuthenticationHandler>(
|
||||
DashboardAuthenticationDefaults.AuthenticationScheme,
|
||||
_ => { });
|
||||
|
||||
// Loud, once-at-startup warning (emitted when GatewayOptions is first resolved).
|
||||
services.AddOptions<GatewayOptions>().PostConfigure<ILoggerFactory>((gatewayOptions, loggerFactory) =>
|
||||
loggerFactory
|
||||
.CreateLogger("ZB.MOM.WW.MxGateway.Server.Dashboard.DisableLogin")
|
||||
.LogWarning(
|
||||
"DASHBOARD LOGIN DISABLED (MxGateway:Dashboard:DisableLogin=true) — every request is "
|
||||
+ "authenticated as '{User}' with full permissions ({Roles}). Dev/test only; never "
|
||||
+ "enable in production.",
|
||||
gatewayOptions.Dashboard.AutoLoginUser ?? DashboardAutoLoginAuthenticationHandler.DefaultUser,
|
||||
$"{DashboardRoles.Admin}, {DashboardRoles.Viewer}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
authentication.AddCookie(DashboardAuthenticationDefaults.AuthenticationScheme, cookieOptions =>
|
||||
{
|
||||
// Hardened defaults (HttpOnly, SameSite=Strict, SecurePolicy, SlidingExpiration,
|
||||
// ExpireTimeSpan) via the shared ZbCookieDefaults.Apply. requireHttps is set to
|
||||
@@ -73,10 +101,12 @@ public static class DashboardServiceCollectionExtensions
|
||||
cookieOptions.LoginPath = "/login";
|
||||
cookieOptions.LogoutPath = "/logout";
|
||||
cookieOptions.AccessDeniedPath = "/denied";
|
||||
})
|
||||
.AddScheme<AuthenticationSchemeOptions, HubTokenAuthenticationHandler>(
|
||||
DashboardAuthenticationDefaults.HubAuthenticationScheme,
|
||||
_ => { });
|
||||
});
|
||||
}
|
||||
|
||||
authentication.AddScheme<AuthenticationSchemeOptions, HubTokenAuthenticationHandler>(
|
||||
DashboardAuthenticationDefaults.HubAuthenticationScheme,
|
||||
_ => { });
|
||||
|
||||
// Honour DashboardOptions.RequireHttpsCookie (default true / Always; set false for dev
|
||||
// HTTP deployments → SameAsRequest) and the optional per-environment cookie-name
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ZB.MOM.WW.MxGateway.Server;
|
||||
using ZB.MOM.WW.MxGateway.Server.Dashboard;
|
||||
|
||||
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
|
||||
|
||||
public sealed class DashboardDisableLoginTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task DisableLoginOff_CookieSchemeUsesCookieHandler()
|
||||
{
|
||||
await using WebApplication app = GatewayApplication.Build([]);
|
||||
IAuthenticationSchemeProvider provider =
|
||||
app.Services.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
|
||||
AuthenticationScheme? scheme = await provider.GetSchemeAsync(
|
||||
DashboardAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal(typeof(CookieAuthenticationHandler), scheme!.HandlerType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisableLoginOn_CookieSchemeUsesAutoLoginHandler()
|
||||
{
|
||||
await using WebApplication app = GatewayApplication.Build(
|
||||
["--MxGateway:Dashboard:DisableLogin=true"]);
|
||||
IAuthenticationSchemeProvider provider =
|
||||
app.Services.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
|
||||
AuthenticationScheme? scheme = await provider.GetSchemeAsync(
|
||||
DashboardAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal(typeof(DashboardAutoLoginAuthenticationHandler), scheme!.HandlerType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisableLoginOn_AutoLoginPrincipalSatisfiesAdminAndViewerPolicies()
|
||||
{
|
||||
await using WebApplication app = GatewayApplication.Build(
|
||||
["--MxGateway:Dashboard:DisableLogin=true"]);
|
||||
IAuthorizationService authorization =
|
||||
app.Services.GetRequiredService<IAuthorizationService>();
|
||||
ClaimsPrincipal user = DashboardAutoLoginAuthenticationHandler.CreatePrincipal("multi-role");
|
||||
|
||||
Assert.True((await authorization.AuthorizeAsync(
|
||||
user, resource: null, DashboardAuthenticationDefaults.AdminPolicy)).Succeeded);
|
||||
Assert.True((await authorization.AuthorizeAsync(
|
||||
user, resource: null, DashboardAuthenticationDefaults.ViewerPolicy)).Succeeded);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user