Orleans.Lattice.Explorer.Entra.Web architecture
This page documents Orleans.Lattice.Explorer.Entra.Web, which is in progress, in the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at architecture.md, and llms.txt lists every page.The package bridges two authentication layers: the browser's OpenID Connect session with Entra, and the Explorer auth method that produces a bearer credential for the State API.
The two layers
flowchart TD
Browser[Browser] -->|1. unauthenticated request| Middleware[ASP.NET OpenID Connect middleware]
Middleware -->|2. redirect, auth code, PKCE| Entra[Microsoft Entra ID]
Entra -->|3. cookie session| Browser
Browser -->|4. Blazor Server circuit| Circuit[Auto-sign-in circuit handler]
Circuit -->|5. LoginWithMethod entra| Method[EntraWebExplorerAuthMethod]
Method -->|6. acquire State API token| Acquirer[IExplorerWebTokenAcquirer]
Acquirer -->|7. ClaimsPrincipal plus scopes| IdentityWeb[Microsoft.Identity.Web]
Method -->|8. bearer credential| StateApi[State API]
- Browser session.
AddLatticeExplorerEntraWebAuthcallsAddMicrosoftIdentityWebApp, using the standard authorization-code + PKCE OpenID Connect flow with a cookie session. WhenRequireAuthenticatedUseris true, a fallback authorization policy challenges unauthenticated requests. - State API credential. Once the browser has a cookie session, the Explorer
still needs a State API bearer token.
EntraWebExplorerAuthMethodhandles theentrascheme and delegates token acquisition toIExplorerWebTokenAcquirer.
The session chrome offers the entra sign-in method when the endpoint advertises
it. The OIDC redirect is driven by ASP.NET Core middleware, outside the SignalR
circuit.
Token acquisition without an ambient HttpContext
A remote Blazor Server circuit runs over SignalR and has no ambient
HttpContext. The Microsoft.Identity.Web-backed acquirer therefore:
- reads the circuit user from the scoped
AuthenticationStateProvider; - throws
ExplorerWebReauthRequiredExceptionif the circuit is anonymous; - calls
ITokenAcquisition.GetAuthenticationResultForUserAsyncwith theClaimsPrincipalpassed explicitly; - translates
MsalUiRequiredExceptionandMicrosoftIdentityWebChallengeUserExceptionintoExplorerWebReauthRequiredException.
The registration calls AddCascadingAuthenticationState() so the circuit sees
the OpenID Connect identity captured during the HTTP render. Without that, the
page could be authenticated at the HTTP layer while the circuit sees an
anonymous user and all downstream State API calls remain anonymous.
Scope resolution
EntraWebExplorerAuthMethod resolves downstream scopes in priority order:
ExplorerEntraWebOptions.Scopes, when non-empty.- The audience advertised by the State API, appending
/.defaultwhen the advertised value is a bare resource id.
If neither source provides a scope, sign-in fails with an actionable exception.
Renewal and revocation
The auth method wraps the acquired token in ExplorerAccessTokenSource. Renewal
runs through the token acquirer again. When acquisition raises
ExplorerWebReauthRequiredException, the renewal delegate returns null; the
source latches into its revoked state and the session chrome shows the Your session expired interstitial.
The initial token acquisition of a new sign-in is outside that latch path, so its failure surfaces directly to the sign-in flow.
Auto-sign-in circuit handler
When AutoSignIn is true, a scoped circuit handler runs when a Blazor Server
circuit connects:
- If the Explorer auth session is already authenticated, it does nothing.
- If the browser principal is anonymous, it logs a warning and returns.
- Otherwise it initialises the Explorer session, initialises the auth session,
discovers the endpoint's advertised schemes, and calls
LoginWithMethodAsyncforentraonly when that scheme is advertised.
Any exception is logged as a warning and swallowed. Auto-sign-in is a convenience, not a correctness boundary; the user can still sign in through the dialog.
Token cache and multi-replica hosting
Microsoft.Identity.Web caches acquired tokens. ExplorerWebTokenCacheKind.InMemory
is per process and correct for a single replica. On a multi-replica host, a user
routed to a cold replica has a valid cookie but no token in that replica's cache,
so token acquisition requires interaction.
Set TokenCache to Distributed and register a shared IDistributedCache so
any replica can find the token. Share the ASP.NET Data Protection key ring as
well so every replica can decrypt the browser session cookie. See
multi-replica and failover hosting.
Federated sign-out and CSP
When SignOutPath is set, the provider publishes ExplorerSignOutOptions so the
identity menu posts to the federated sign-out endpoint. The endpoint validates
antiforgery, clears the local State API credential, clears the OpenID Connect
cookie and signs out of Entra.
The provider also adds the configured Entra authority origin to the Explorer web
head's form-action CSP sources when the authority parses as an HTTP or HTTPS
origin. This allows the local sign-out POST to redirect to Entra's end-session
endpoint without loosening other CSP directives.