using System.Net; using System.Security.Claims; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using MxGateway.Server.Configuration; using MxGateway.Server.Dashboard; using MxGateway.Server.Security.Authorization; namespace MxGateway.Tests.Gateway.Dashboard; public sealed class DashboardAuthorizationHandlerTests { /// Verifies that unauthenticated remote requests fail authorization. [Fact] public async Task HandleAsync_UnauthenticatedRemoteRequest_DoesNotSucceed() { AuthorizationHandlerContext context = await AuthorizeAsync( new ClaimsPrincipal(new ClaimsIdentity()), IPAddress.Parse("10.0.0.5"), allowAnonymousLocalhost: false); Assert.False(context.HasSucceeded); } /// Verifies that anonymous localhost access succeeds when allowed. [Fact] public async Task HandleAsync_AnonymousLocalhostAllowed_Succeeds() { AuthorizationHandlerContext context = await AuthorizeAsync( new ClaimsPrincipal(new ClaimsIdentity()), IPAddress.Loopback, allowAnonymousLocalhost: true); Assert.True(context.HasSucceeded); } /// Verifies that authenticated users without admin scope fail authorization. [Fact] public async Task HandleAsync_AuthenticatedWithoutAdminScope_DoesNotSucceed() { AuthorizationHandlerContext context = await AuthorizeAsync( CreatePrincipal(GatewayScopes.EventsRead), IPAddress.Loopback, allowAnonymousLocalhost: false); Assert.False(context.HasSucceeded); } /// Verifies that authenticated users with admin scope succeed. [Fact] public async Task HandleAsync_AuthenticatedWithAdminScope_Succeeds() { AuthorizationHandlerContext context = await AuthorizeAsync( CreatePrincipal(GatewayScopes.Admin), IPAddress.Parse("10.0.0.5"), allowAnonymousLocalhost: false); Assert.True(context.HasSucceeded); } private static async Task AuthorizeAsync( ClaimsPrincipal principal, IPAddress remoteAddress, bool allowAnonymousLocalhost) { DashboardAuthorizationRequirement requirement = new(); DefaultHttpContext httpContext = new(); httpContext.Connection.RemoteIpAddress = remoteAddress; DashboardAuthorizationHandler handler = new( new HttpContextAccessor { HttpContext = httpContext }, Options.Create(new GatewayOptions { Dashboard = new DashboardOptions { AllowAnonymousLocalhost = allowAnonymousLocalhost, RequireAdminScope = true } })); AuthorizationHandlerContext context = new([requirement], principal, httpContext); await handler.HandleAsync(context); return context; } private static ClaimsPrincipal CreatePrincipal(string scope) { ClaimsIdentity identity = new( [new Claim(DashboardAuthenticationDefaults.ScopeClaimType, scope)], DashboardAuthenticationDefaults.AuthenticationScheme); return new ClaimsPrincipal(identity); } }