using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using ScadaLink.Security;
namespace ScadaLink.CentralUI.Auth;
///
/// Minimal API endpoints for login/logout. These run outside Blazor Server (standard HTTP POST).
/// On success, signs in via ASP.NET Core cookie authentication and redirects to dashboard.
///
public static class AuthEndpoints
{
public static IEndpointRouteBuilder MapAuthEndpoints(this IEndpointRouteBuilder endpoints)
{
endpoints.MapPost("/auth/login", async (HttpContext context) =>
{
var form = await context.Request.ReadFormAsync();
var username = form["username"].ToString();
var password = form["password"].ToString();
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
{
context.Response.Redirect("/login?error=Username+and+password+are+required.");
return;
}
var ldapAuth = context.RequestServices.GetRequiredService();
var jwtService = context.RequestServices.GetRequiredService();
var roleMapper = context.RequestServices.GetRequiredService();
var authResult = await ldapAuth.AuthenticateAsync(username, password);
if (!authResult.Success)
{
var errorMsg = Uri.EscapeDataString(authResult.ErrorMessage ?? "Authentication failed.");
context.Response.Redirect($"/login?error={errorMsg}");
return;
}
// Map LDAP groups to roles
var roleMappingResult = await roleMapper.MapGroupsToRolesAsync(authResult.Groups ?? []);
// Build claims from LDAP auth + role mapping
var claims = new List
{
new(ClaimTypes.Name, authResult.Username ?? username),
new(JwtTokenService.DisplayNameClaimType, authResult.DisplayName ?? username),
new(JwtTokenService.UsernameClaimType, authResult.Username ?? username),
};
foreach (var role in roleMappingResult.Roles)
{
claims.Add(new Claim(JwtTokenService.RoleClaimType, role));
}
if (!roleMappingResult.IsSystemWideDeployment)
{
foreach (var siteId in roleMappingResult.PermittedSiteIds)
{
claims.Add(new Claim(JwtTokenService.SiteIdClaimType, siteId));
}
}
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await context.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
principal,
new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(30)
});
context.Response.Redirect("/");
}).DisableAntiforgery();
endpoints.MapPost("/auth/logout", async (HttpContext context) =>
{
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
context.Response.Redirect("/login");
}).DisableAntiforgery();
return endpoints;
}
}