WBS-11 BFF Hardening: Implement auth caching state provider for instant sidebar transitions, forward proxy authentication cookies, and resolve WASM server-side prerendering BaseAddress null exception
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 8s
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 14s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Deploy to Production / Build & Deploy to Production (push) Failing after 3m7s
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 8s
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 14s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Deploy to Production / Build & Deploy to Production (push) Failing after 3m7s
This commit is contained in:
@@ -93,7 +93,11 @@ builder.Services.AddScoped<IKisApiClient, KisApiClient>();
|
||||
// builder.Services.AddScoped<ICollectionOrchestrator, KisDataCollectionOrchestrator>();
|
||||
// builder.Services.AddScoped<DataCollectionService>();
|
||||
|
||||
builder.Services.AddHttpClient<ApiClient>();
|
||||
builder.Services.AddHttpClient<ApiClient>(client =>
|
||||
{
|
||||
// Configure default base address for relative HttpClient calls within server assembly calls
|
||||
client.BaseAddress = new Uri("http://localhost:5265/");
|
||||
});
|
||||
builder.Services.AddScoped<ApiClient>();
|
||||
builder.Services.AddFastEndpoints();
|
||||
|
||||
@@ -183,13 +187,15 @@ catch (Exception ex)
|
||||
Log.Warning("Hangfire setup failed: {Message}", ex.Message);
|
||||
}
|
||||
|
||||
// Root path - redirect unauthenticated to /login.html (static file)
|
||||
// Root path - redirect unauthenticated to /Account/Login (secure SSR Razor Page)
|
||||
app.MapGet("/", async (HttpContext ctx) =>
|
||||
{
|
||||
var isAuthenticated = ctx.User?.Identity?.IsAuthenticated ?? false;
|
||||
if (!isAuthenticated)
|
||||
// Check cookie parity for server-side root routing redirect
|
||||
var hasCookie = ctx.Request.Cookies.ContainsKey("quant_auth_token");
|
||||
if (!isAuthenticated && !hasCookie)
|
||||
{
|
||||
ctx.Response.Redirect("/login.html");
|
||||
ctx.Response.Redirect("/Account/Login");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -199,10 +205,10 @@ app.MapGet("/", async (HttpContext ctx) =>
|
||||
await Task.CompletedTask;
|
||||
});
|
||||
|
||||
// Map /login to static login.html
|
||||
// Map /login to secure SSR Razor Page /Account/Login
|
||||
app.MapGet("/login", (HttpContext ctx) =>
|
||||
{
|
||||
ctx.Response.Redirect("/login.html", permanent: false);
|
||||
ctx.Response.Redirect("/Account/Login", permanent: false);
|
||||
});
|
||||
|
||||
// Login API (API-First for Blazor WASM client authentication)
|
||||
@@ -243,6 +249,8 @@ app.MapPost("/api/auth/login", async (JsonElement payload, HttpContext httpConte
|
||||
var devToken = Guid.NewGuid().ToString("N");
|
||||
var devExpiresAt = DateTimeOffset.UtcNow.AddDays(7);
|
||||
|
||||
var devIsSecureEnv = httpContext.Request.IsHttps;
|
||||
|
||||
// Set HTTP-only cookie for dev fallback too
|
||||
httpContext.Response.Cookies.Append(
|
||||
"quant_auth_token",
|
||||
@@ -250,7 +258,7 @@ app.MapPost("/api/auth/login", async (JsonElement payload, HttpContext httpConte
|
||||
new Microsoft.AspNetCore.Http.CookieOptions
|
||||
{
|
||||
HttpOnly = true,
|
||||
Secure = true,
|
||||
Secure = devIsSecureEnv,
|
||||
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax,
|
||||
Expires = devExpiresAt,
|
||||
Path = "/"
|
||||
@@ -299,13 +307,15 @@ app.MapPost("/api/auth/login", async (JsonElement payload, HttpContext httpConte
|
||||
Console.WriteLine($"[Auth/Login] Setting cookie 'quant_auth_token'");
|
||||
Console.WriteLine($"[Auth/Login] IsHttps: {httpContext.Request.IsHttps}");
|
||||
|
||||
var isSecureEnv = httpContext.Request.IsHttps;
|
||||
|
||||
httpContext.Response.Cookies.Append(
|
||||
"quant_auth_token",
|
||||
rawToken,
|
||||
new Microsoft.AspNetCore.Http.CookieOptions
|
||||
{
|
||||
HttpOnly = true,
|
||||
Secure = true, // Force Secure Cookie for SSL standard
|
||||
Secure = isSecureEnv, // Dynamic SSL Secure binding based on active request env
|
||||
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax,
|
||||
Expires = expiresAt,
|
||||
Path = "/"
|
||||
@@ -539,8 +549,8 @@ internal sealed class QuantAdminAuthHandler : AuthenticationHandler<Authenticati
|
||||
|
||||
protected override Task HandleChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
// Instead of hard 401 response which breaks routing or triggers static page redirects, redirect to login page
|
||||
Response.Redirect("/login.html");
|
||||
// Redirect securely to Razor Page Login endpoint
|
||||
Response.Redirect("/Account/Login");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user