using System.Net; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Options; using MxGateway.Server.Configuration; using MxGateway.Server.Security.Authorization; namespace MxGateway.Server.Dashboard; public sealed class DashboardAuthorizationHandler( IHttpContextAccessor httpContextAccessor, IOptions options) : AuthorizationHandler { protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, DashboardAuthorizationRequirement requirement) { GatewayOptions gatewayOptions = options.Value; if (gatewayOptions.Authentication.Mode == AuthenticationMode.Disabled) { context.Succeed(requirement); return Task.CompletedTask; } if (gatewayOptions.Dashboard.AllowAnonymousLocalhost && IsLoopbackRequest()) { context.Succeed(requirement); return Task.CompletedTask; } if (context.User.Identity?.IsAuthenticated != true) { return Task.CompletedTask; } if (!gatewayOptions.Dashboard.RequireAdminScope || HasAdminScope(context)) { context.Succeed(requirement); } return Task.CompletedTask; } private bool IsLoopbackRequest() { IPAddress? remoteAddress = httpContextAccessor.HttpContext?.Connection.RemoteIpAddress; return remoteAddress is not null && IPAddress.IsLoopback(remoteAddress); } private static bool HasAdminScope(AuthorizationHandlerContext context) { return context.User.HasClaim( DashboardAuthenticationDefaults.ScopeClaimType, GatewayScopes.Admin); } }