using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using ZB.MOM.WW.Auth.Abstractions.Roles; using ZB.MOM.WW.Auth.AspNetCore; using ZB.MOM.WW.MxGateway.Server.Configuration; using ZB.MOM.WW.MxGateway.Server.Security.Audit; namespace ZB.MOM.WW.MxGateway.Server.Dashboard; /// /// Extension methods for configuring the gateway dashboard services. /// public static class DashboardServiceCollectionExtensions { /// /// Registers all dashboard services, authentication, and Razor components. /// /// Service collection to register services. /// /// Application configuration, used to bind the shared LDAP provider's options /// from the MxGateway:Ldap section. /// public static IServiceCollection AddGatewayDashboard( this IServiceCollection services, IConfiguration configuration) { // Dashboard logins delegate bind/search to the shared ZB.MOM.WW.Auth.Ldap // provider. Its LdapOptions bind straight from MxGateway:Ldap (the gateway's // LdapOptions field names match the shared options: Transport / AllowInsecure / // SearchBase / ServiceAccount* / *Attribute). AddZbLdapAuth also adds a // ValidateOnStart() so an insecure-transport misconfiguration fails fast at boot. services.AddZbLdapAuth(configuration, "MxGateway:Ldap"); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton, DashboardGroupRoleMapper>(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddScoped(); services.AddScoped(); services.AddSingleton(); services.AddHostedService(); services.AddHostedService(); services.AddHttpContextAccessor(); services.AddSingleton(); services.AddAntiforgery(); services.AddCascadingAuthenticationState(); services.AddRazorComponents() .AddInteractiveServerComponents(); services.AddSignalR(); services .AddAuthentication(DashboardAuthenticationDefaults.AuthenticationScheme) .AddCookie(DashboardAuthenticationDefaults.AuthenticationScheme, cookieOptions => { // Hardened defaults (HttpOnly, SameSite=Strict, SecurePolicy, SlidingExpiration, // ExpireTimeSpan) via the shared ZbCookieDefaults.Apply. requireHttps is set to // its default (true / Always) here and overridden per-environment by the // PostConfigure below; the 8-hour idle timeout is preserved (not the 30-min default). ZbCookieDefaults.Apply(cookieOptions, requireHttps: true, idleTimeout: TimeSpan.FromHours(8)); // Cookie name, path, and redirect paths are MxGateway-specific — set after Apply // so they are never overwritten by the shared helper (Apply intentionally skips name). // This is the canonical default; it is overridden per-environment from // DashboardOptions.CookieName by the PostConfigure below. cookieOptions.Cookie.Name = DashboardAuthenticationDefaults.CookieName; cookieOptions.Cookie.Path = "/"; cookieOptions.LoginPath = "/login"; cookieOptions.LogoutPath = "/logout"; cookieOptions.AccessDeniedPath = "/denied"; }) .AddScheme( DashboardAuthenticationDefaults.HubAuthenticationScheme, _ => { }); // Honour DashboardOptions.RequireHttpsCookie (default true / Always; set false for dev // HTTP deployments → SameAsRequest) and the optional per-environment cookie-name // override. Both run after the inline AddCookie config above, so they win. services.AddOptions(DashboardAuthenticationDefaults.AuthenticationScheme) .Configure>((cookieOptions, gatewayOptions) => { cookieOptions.Cookie.SecurePolicy = gatewayOptions.Value.Dashboard.RequireHttpsCookie ? CookieSecurePolicy.Always : CookieSecurePolicy.SameAsRequest; // Config-driven cookie name (MxGateway:Dashboard:CookieName). Null/blank keeps // the canonical default set above, so a misconfiguration cannot unname the cookie. var cookieName = gatewayOptions.Value.Dashboard.CookieName; if (!string.IsNullOrWhiteSpace(cookieName)) { cookieOptions.Cookie.Name = cookieName; } }); services.AddAuthorization(authorization => { authorization.AddPolicy( DashboardAuthenticationDefaults.ViewerPolicy, policy => policy.AddRequirements(DashboardAuthorizationRequirement.AnyDashboardRole)); authorization.AddPolicy( DashboardAuthenticationDefaults.AdminPolicy, policy => policy.AddRequirements(DashboardAuthorizationRequirement.AdminOnly)); authorization.AddPolicy( DashboardAuthenticationDefaults.HubClientsPolicy, policy => policy .AddAuthenticationSchemes( DashboardAuthenticationDefaults.AuthenticationScheme, DashboardAuthenticationDefaults.HubAuthenticationScheme) .AddRequirements(DashboardAuthorizationRequirement.AnyDashboardRole)); }); services.AddSingleton(); return services; } }