Fix stuck-on-loading after sign-in; enable HTTP/LAN local login
The app stuck on "Chargement…" after sign-in because the interactive Blazor circuit came up anonymous: no auth cookie reached this origin. Root cause was the deployment (plain HTTP on an IP, http://host:8080), which Microsoft OIDC cannot serve — Entra forbids http redirect URIs for non-localhost hosts, so the sign-in cookie never lands on the origin. Changes: - ForwardedHeaders (X-Forwarded-Proto/For) so that behind a TLS proxy the app sees the real https scheme, builds a matching OIDC redirect_uri, and sets the auth cookie Secure. Proxy IP unknown in-container → known proxy/network restrictions cleared. - First-run bootstrap: seed a local admin (Bootstrap__AdminEmail / Bootstrap__AdminPassword) when that email has no account, so HTTP/LAN deployments that can't use OIDC can sign in via the local form. Idempotent. - OIDC SaveTokens=false: the cookie-stored access/id/refresh tokens were never read (SharePoint/Graph auth uses the separate connect-flow + cert paths). Dropping them keeps the auth cookie small/unchunked. - AppInitializer now logs which branch leaves UserContext unseeded (unauthenticated principal / missing claim / no user row) instead of failing silently — this is what surfaced the anonymous-circuit cause. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
@inject AuthenticationStateProvider AuthProvider
|
||||
@inject IUserService UserService
|
||||
@inject IUserContextAccessor UserContext
|
||||
@inject ILogger<AppInitializer> Logger
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using SharepointToolbox.Web.Services.Auth
|
||||
@using SharepointToolbox.Web.Services.Session
|
||||
@@ -12,13 +13,30 @@
|
||||
{
|
||||
var state = await AuthProvider.GetAuthenticationStateAsync();
|
||||
var principal = state.User;
|
||||
if (principal.Identity?.IsAuthenticated != true) return;
|
||||
|
||||
if (principal.Identity?.IsAuthenticated != true)
|
||||
{
|
||||
Logger.LogWarning("AppInitializer: circuit principal NOT authenticated; UserContext left unseeded → page stays on loading.");
|
||||
return;
|
||||
}
|
||||
|
||||
var email = principal.FindFirst("preferred_username")?.Value
|
||||
?? principal.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;
|
||||
if (string.IsNullOrEmpty(email)) return;
|
||||
if (string.IsNullOrEmpty(email))
|
||||
{
|
||||
var claims = string.Join(", ", principal.Claims.Select(c => $"{c.Type}={c.Value}"));
|
||||
Logger.LogWarning("AppInitializer: authenticated but no preferred_username/email claim. Claims present: [{Claims}]", claims);
|
||||
return;
|
||||
}
|
||||
|
||||
var user = await UserService.GetByEmailAsync(email);
|
||||
if (user is not null) UserContext.Initialize(user);
|
||||
if (user is null)
|
||||
{
|
||||
Logger.LogWarning("AppInitializer: no user row for email '{Email}' — provisioning did not persist a matching record.", email);
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInformation("AppInitializer: seeded UserContext for '{Email}' (role {Role}).", user.Email, user.Role);
|
||||
UserContext.Initialize(user);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user