Fix OIDC stuck-on-loading: slim auth cookie principal
The OIDC OnTokenValidated handler stored the raw principal (all id_token + userinfo claims) in the auth cookie. Encrypted + base64 it exceeds ~4 KB, so ChunkingCookieManager splits it across …CookiesC1/C2. The chunked cookie survives the prerender GET but is dropped on the Blazor interactive WebSocket upgrade, so the circuit comes up anonymous and the page sticks on "Chargement…". SaveTokens=false alone didn't shrink it enough — the claims themselves bloat it. Replace the principal with a slim 4-claim identity (preferred_username, name, app_role, auth_provider), identical to the local-login path, so the cookie stays single + unchunked and the circuit authenticates. Also fixes a latent bug: the OIDC principal never carried app_role or auth_provider, so Entra admins got no admin nav and logout skipped the OIDC sign-out branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+23
-1
@@ -131,7 +131,29 @@ else
|
|||||||
options.Events.OnTokenValidated = async ctx =>
|
options.Events.OnTokenValidated = async ctx =>
|
||||||
{
|
{
|
||||||
var userService = ctx.HttpContext.RequestServices.GetRequiredService<IUserService>();
|
var userService = ctx.HttpContext.RequestServices.GetRequiredService<IUserService>();
|
||||||
await userService.ProvisionAsync(ctx.Principal!);
|
var user = await userService.ProvisionAsync(ctx.Principal!);
|
||||||
|
|
||||||
|
// The whole principal is serialized into the auth cookie. The raw OIDC principal carries
|
||||||
|
// dozens of id_token + userinfo claims (oid, tid, given/family_name, a long picture URL …);
|
||||||
|
// encrypted + base64 it exceeds ~4 KB, so ChunkingCookieManager splits it into …CookiesC1/C2.
|
||||||
|
// The chunked cookie survives the prerender GET but is dropped on the Blazor WebSocket upgrade
|
||||||
|
// → the interactive circuit comes up anonymous → page sticks on "Chargement…". Replace it with
|
||||||
|
// a slim principal holding only the claims the app reads — identical to the local-login path —
|
||||||
|
// so the cookie stays small (single, unchunked) and the circuit authenticates. This also adds
|
||||||
|
// the app_role claim (role-based authz) and auth_provider (logout's OIDC sign-out branch),
|
||||||
|
// which the fat OIDC principal never had.
|
||||||
|
var identity = new ClaimsIdentity(
|
||||||
|
new Claim[]
|
||||||
|
{
|
||||||
|
new("preferred_username", user.Email),
|
||||||
|
new("name", user.DisplayName),
|
||||||
|
new("app_role", user.Role.ToString()),
|
||||||
|
new("auth_provider", nameof(AuthProvider.Entra)),
|
||||||
|
},
|
||||||
|
ctx.Principal!.Identity!.AuthenticationType,
|
||||||
|
"preferred_username",
|
||||||
|
"app_role");
|
||||||
|
ctx.Principal = new ClaimsPrincipal(identity);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user