Skip to content

[Blazor] Propagate SignalR authentication refresh to server circuits - #68221

Open
kotlarmilos wants to merge 2 commits into
dotnet:mainfrom
kotlarmilos:blazor-auth-refresh-circuit-user
Open

[Blazor] Propagate SignalR authentication refresh to server circuits#68221
kotlarmilos wants to merge 2 commits into
dotnet:mainfrom
kotlarmilos:blazor-auth-refresh-circuit-user

Conversation

@kotlarmilos

@kotlarmilos kotlarmilos commented Aug 5, 2026

Copy link
Copy Markdown
Member

Description

ComponentHub now overrides Hub.OnAuthenticationRefreshedAsync so a Blazor server circuit picks up a refreshed principal without reconnecting. SignalR can refresh the authentication of an active connection through the /refresh endpoint added in #67111 and #67964, and it notifies a hub by calling that method. ComponentHub did not override it, so the circuit kept the principal it captured when the connection was established. AuthorizeView and other AuthenticationStateProvider consumers showed a stale user until the circuit reconnected.

The override passes Context.User to CircuitHost.SetCircuitUser, which is the same call ConnectCircuit already makes when a circuit reattaches to a new connection. SetCircuitUser sets the state on IHostEnvironmentAuthenticationStateProvider, which raises AuthenticationStateChanged and re-renders the affected components.

No public API is added. Applications opt in through the existing EnableAuthenticationRefresh option on the server and configureSignalR in Blazor.start on the client.

Fixes #68170

SignalR can refresh the authentication of an active connection through the
/refresh endpoint, and it notifies hubs by calling Hub.OnAuthenticationRefreshedAsync.
ComponentHub did not override that method, so a Blazor Server circuit kept serving
the principal captured when the connection was established. AuthorizeView and every
other AuthenticationStateProvider consumer continued to observe the stale user until
the circuit reconnected.

ComponentHub now overrides OnAuthenticationRefreshedAsync and forwards Context.User
to CircuitHost.SetCircuitUser, which is the same call ConnectCircuit already makes
when a circuit is reattached to a new connection. SetCircuitUser pushes the principal
through IHostEnvironmentAuthenticationStateProvider, so AuthenticationStateChanged
fires and components re-render against the refreshed user. No public API is added,
and the existing opt-in surfaces remain unchanged.

Fixes dotnet#68170

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a850277c-a3e3-4c6b-970a-834ae5a89b2d
@kotlarmilos
kotlarmilos marked this pull request as ready for review August 5, 2026 10:33
Copilot AI review requested due to automatic review settings August 5, 2026 10:33
@kotlarmilos
kotlarmilos requested a review from a team as a code owner August 5, 2026 10:33
@kotlarmilos kotlarmilos self-assigned this Aug 5, 2026
@kotlarmilos kotlarmilos added the area-blazor Includes: Blazor, Razor Components label Aug 5, 2026
@kotlarmilos kotlarmilos added this to the 11.0-rc1 milestone Aug 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enables Blazor Server circuits to observe SignalR authentication refresh updates without requiring a reconnect, by flowing the refreshed ClaimsPrincipal into the circuit so AuthenticationStateProvider consumers (e.g., AuthorizeView) re-render with the new identity.

Changes:

  • Override ComponentHub.OnAuthenticationRefreshedAsync to update the circuit user via CircuitHost.SetCircuitUser(Context.User).
  • Add unit coverage for the hub callback behavior (updates circuit user; no-op when no circuit is associated).
  • Add an E2E scenario that refreshes auth via /refresh and asserts UI updates without renegotiating/reconnecting.
Show a summary per file
File Description
src/Components/Server/src/ComponentHub.cs Adds OnAuthenticationRefreshedAsync override to propagate refreshed principal into the circuit.
src/Components/Server/test/Circuits/ComponentHubTest.cs Adds unit tests validating circuit user updates on auth refresh.
src/Components/test/testassets/Components.TestServer/AuthenticationStartup.cs Enables authentication refresh for the Blazor hub in the test server.
src/Components/test/testassets/Components.TestServer/Pages/_ServerHost.cshtml Adds test-only fetch interception + helper to invoke the /refresh endpoint from JS.
src/Components/test/E2ETest/Tests/AuthTest.cs Allows app navigation to include an optional query string for test hooks.
src/Components/test/E2ETest/ServerExecutionTests/ServerAuthTest.cs Adds E2E test ensuring refreshed auth updates AuthorizeView output without renegotiation.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 2

Comment thread src/Components/test/E2ETest/ServerExecutionTests/ServerAuthTest.cs
Comment thread src/Components/Server/test/Circuits/ComponentHubTest.cs
@javiercn
javiercn requested a review from BrennanConroy August 5, 2026 10:43
@kotlarmilos kotlarmilos added feature-response-caching and removed area-blazor Includes: Blazor, Razor Components labels Aug 5, 2026
Report a rejected refresh promise through the async script callback, so a
failed refresh fails the assertion with the error text instead of blocking
until the Selenium script timeout.

Default the mocked HubCallerContext.User to an empty ClaimsPrincipal, matching
how HubConnectionContext.User normalizes a null principal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a850277c-a3e3-4c6b-970a-834ae5a89b2d
@kotlarmilos kotlarmilos added area-blazor Includes: Blazor, Razor Components and removed feature-response-caching labels Aug 5, 2026
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
if (new URLSearchParams(location.search).has('captureAuthenticationRefresh')) {
const originalFetch = window.fetch;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really hacky, I don't know if you want this in the code base. Ideally, you'd either get the HubConnection and call the refresh method, or have a short lived token that causes the automatic refresh to occur (yes I know that would cause the test to not be instant anymore).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Blazor] Consume SignalR authentication refresh in Blazor Server circuits

3 participants