v11 update: SignalR .NET client supports authentication refresh after redirects

Open Beginner friendly
#37,694 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Documentation
Clarity
Clearly specified
Activity status
Active
Tech stack
csharp
Domain
documentation

Research direction

Start in aspnetcore/signalr/authn-and-authz.md at the .NET 11 Authentication refresh section around lines 275–279, then review the linked HttpConnection.cs and release note for redirect behavior. Done means the article explains app and transport tokens, refresh scheduling after redirects, and the current Azure SignalR Service limitation within the existing .NET 11 moniker zone.

Written by the indexing model from the issue text.

Description

11.0 SignalR

[!NOTE]
This is an AI-assisted coverage analysis of the What's new in ASP.NET Core in .NET 11 release note, reviewed by a human before filing. Every line number and permalink refers to the pinned commits below. Companion issue: the core authentication refresh feature is covered in https://github.com/dotnet/AspNetCore.Docs/issues/37691, which edits the same article.

Target repository: dotnet/AspNetCore.Docs
Analyzed at commit: 4986136881f2bbf1879f10106467769df5a49932
Product source verified at: dotnet/aspnetcore @ 1fcd7ef305697a1888f3ede076010350ae9f4f8d
Source release note: SignalR .NET client supports authentication refresh after redirects


🎯 Goal

The authentication refresh feature itself is well documented — see dotnet/AspNetCore.Docs#37691 for the verification record. What's missing is everything specific to this sub-area: not one article in the docset mentions negotiate redirects in connection with authentication refresh, and no article mentions Azure SignalR Service in that context either. A docset-wide search for "redirect" scoped to aspnetcore/signalr/ returns only reconnection and HTTPS-redirection content.

This matters more than a typical discoverability gap because the release note itself flags a deployment trap: the client-side support exists, but the redirecting server most readers will use — Azure SignalR Service — hasn't enabled the server half yet. A reader who enables WithAuthenticationRefresh behind Azure SignalR today gets a connection that never schedules a refresh, with nothing in the docs explaining why.

This report proposes one change: a short subsection in the existing .NET 11 Authentication refresh section of xref:signalr/authn-and-authz covering redirect behavior and the current Azure SignalR status.


✅ Coverage status summary

Legend: ✅ already documented · ✏️ update needed · 🟣 could not determine

# Feature element from What's New Status Where
1 Authentication refresh works when negotiate redirects to another server ✏️ 1. Updateaspnetcore/signalr/authn-and-authz.md L275–L279
2 The client preserves the app-token provider across the redirect and uses it to authenticate the refresh request ✏️ 1. Update
3 The client adopts a refreshed transport token returned by the /refresh response ✏️ 1. Update
4 The reported token lifetime is retained across the redirect so automatic refresh stays scheduled ✏️ 1. Update
5 Redirecting servers such as Azure SignalR Service are the scenario this enables ✏️ 1. Update
6 The .NET client article has no path to authentication refresh at all ✏️ Tracked in dotnet/AspNetCore.Docs#37691, change 4 — not re-proposed here
7 The .NET client refreshes using the connection's AccessTokenProvider authn-and-authz.md L168
8 RefreshAuthenticationAsync returns the new token lifetime reported by the server authn-and-authz.md L170–L183
9 Automatic refresh is scheduled only when the server reports a token lifetime authn-and-authz.md L202, L277
10 Refresh requires a connection that negotiated protocol version 1 or later authn-and-authz.md L277
11 The client feature matrix lists Authentication Refresh at 11.0.0 for the .NET client aspnetcore/signalr/client-features.md L43
12 Whether Azure SignalR Service has enabled the server half 🟣 See Review considerations

🔢 Version applicability

Applies to: CURRENT-ONLY
Target moniker: >= aspnetcore-11.0
Earlier versions affected: None. Authentication refresh doesn't exist before .NET 11, so redirect support for it can't either. Evidence: 326d566Support SignalR authentication refresh after negotiate redirects (#67612), merged 2026-07-21, contributed by @MoChilia. git show --stat on that commit shows it touched exactly three files: HttpConnection.cs, AccessTokenHttpMessageHandler.cs, and a test file. It adds no public API, so nothing changes in PublicAPI.Unshipped.txt.

Article monikerRange Moniker state
aspnetcore/signalr/authn-and-authz.md '>= aspnetcore-3.1' State C — the insertion point at line 277 is inside the existing :::moniker range=">= aspnetcore-11.0" zone spanning L121–L279. Insert directly; no split, no new directives, zone counts unchanged.

📋 Coverage gap summary

Both scenarios that lead a reader here end badly today.

A developer running SignalR behind Azure SignalR Service enables WithAuthenticationRefresh, deploys, and observes that the refresh never fires. xref:signalr/authn-and-authz tells them automatic refresh is scheduled only when the server reports a token lifetime, but nothing tells them their redirecting service doesn't report one yet. There's no way to distinguish "I configured it wrong" from "the service doesn't support this".

A developer writing their own redirecting negotiate endpoint needs to know which token authenticates the /refresh request. This is genuinely subtle: the client keeps two tokens after a redirect. The token from AccessTokenProvider authenticates against the app's own negotiate endpoint, and the token returned in the redirect response authenticates the transport against the redirect target. Refresh uses the first one, and a /refresh response can supply a new value for the second. Nothing in the docset says so, and the distinction isn't guessable.

Feature announced in What's New:

The SignalR .NET client extends SignalR authentication refresh so it works when negotiate redirects to another server, contributed by @MoChilia. This client change enables support for redirecting servers such as Azure SignalR Service, which hasn't enabled the feature yet.

The client preserves the app-token provider across the redirect, adopts a refreshed transport token from the response, and retains tokenLifetimeSeconds so automatic refresh remains scheduled after the original token expires.

Breaking change: No. This is a fix within a feature that's new in the same release.


📁 Affected files

Item Path Lines Section
1. aspnetcore/signalr/authn-and-authz.md 275–279 "Authentication refresh" (end of the .NET 11 zone)

Target article uid: signalr/authn-and-authz


📝 Proposed changes

✏️ 1. Update — aspnetcore/signalr/authn-and-authz.md, insert after line 277

Applies to: >= aspnetcore-11.0 (already the enclosing zone — State C, insert directly)
Location: Line 277, after the closing caveat paragraph and immediately before the :::moniker-end that closes the .NET 11 zone.

Before (lines 275–279):

A hub method that's already running keeps the `Context.User` it started with. Later invocations observe the refreshed `Context.User`. For more information about how SignalR caches the authenticated user, see [User and role changes during the connection lifetime](#user-and-role-changes-during-the-connection-lifetime).

Authentication refresh requires a connection that negotiated protocol version 1 or later. Automatic refresh is scheduled only when the server reports a token lifetime, which typically comes from an authentication scheme that sets an expiration, such as bearer tokens. Windows authentication doesn't report an expiration and isn't tracked or refreshed by this feature.

:::moniker-end

After:

A hub method that's already running keeps the `Context.User` it started with. Later invocations observe the refreshed `Context.User`. For more information about how SignalR caches the authenticated user, see [User and role changes during the connection lifetime](#user-and-role-changes-during-the-connection-lifetime).

Authentication refresh requires a connection that negotiated protocol version 1 or later. Automatic refresh is scheduled only when the server reports a token lifetime, which typically comes from an authentication scheme that sets an expiration, such as bearer tokens. Windows authentication doesn't report an expiration and isn't tracked or refreshed by this feature.

#### Refresh through a redirecting negotiate endpoint

A negotiate endpoint can redirect a client to a different server, which is how Azure SignalR Service and similar services take over the connection. After a redirect, the .NET client holds two tokens:

* The **app token** from the `AccessTokenProvider` configured on the connection. It authenticates requests to the app's own negotiate endpoint.
* The **transport token** returned in the redirect response. It authenticates the transport connection to the redirect target.

The .NET client uses the app token to authenticate refresh requests, so `AccessTokenProvider` continues to be called for each refresh after a redirect. The token lifetime reported by any negotiate response in the redirect chain is retained, so automatic refresh stays scheduled. If the refresh response returns a new transport token, the client adopts it for subsequent transport requests. A self-hosted SignalR server doesn't return one, because the transport token and the app token are the same.

> [!IMPORTANT]
> The redirect target must implement the refresh endpoint for any of this to take effect. As of .NET 11, Azure SignalR Service doesn't support authentication refresh. A connection through a service that doesn't report a token lifetime never schedules an automatic refresh, and `RefreshAuthenticationAsync` fails. Check the service's documentation before enabling authentication refresh in an app that runs behind it.

:::moniker-end

Rationale: This is the article that already documents the whole feature, and the redirect behavior is a property of the feature rather than of the .NET client's transport internals — so it belongs here, inside the existing Authentication refresh section, rather than in a new section of xref:signalr/dotnet-client. dotnet/AspNetCore.Docs#37691 change 4 adds the pointer from the .NET client article that makes this reachable.

Verified against HttpConnection.cs: the redirect loop preserves _appAccessTokenProvider while replacing _accessTokenProvider with the transport token from the redirect response; GetRefreshRequestTokenAsync uses the app-token provider for the refresh request; _initialTokenLifetime is captured from any negotiate in the chain; and RefreshAuthenticationAsync adopts an accessToken from the refresh response by calling UpdateCachedToken when one is present.


✅ 2. Update — TOC

No TOC change required. xref:signalr/authn-and-authz already has a TOC entry, and no new article is proposed.


✅ Action plan

  1. Confirm the Azure SignalR Service statement with the SignalR or Azure SignalR team before publishing. The release note says the service "hasn't enabled the feature yet", which is a point-in-time claim — see Review considerations.
  2. Apply change 1. It's a State C insertion inside an existing >= aspnetcore-11.0 zone, so no moniker directives are added or removed. authn-and-authz.md has 10 :::moniker range= openers and 10 :::moniker-end closers before and after.
  3. Verify the [User and role changes during the connection lifetime](#user-and-role-changes-during-the-connection-lifetime) anchor in the surrounding text still resolves after the insertion, and that the new #### Refresh through a redirecting negotiate endpoint heading produces a unique anchor.
  4. Coordinate with dotnet/AspNetCore.Docs#37691, which edits the same article. Apply that issue's changes 1 and 2 first (they're earlier in the file) or this change first (it's later in the file) — either order works as long as the line numbers used are re-read after the first edit lands.
  5. Build and confirm the new content renders under the .NET 11 selector only.
  6. Resolve any OpenPublishing.Build warnings.

⚠️ Review considerations

  • 🟣 Has Azure SignalR Service enabled authentication refresh since the release note was written? This audit can verify the ASP.NET Core client and server halves from dotnet/aspnetcore source, but Azure SignalR Service is a separate, closed-source service. The IMPORTANT note in change 1 is worded as a point-in-time statement about .NET 11 for that reason. If the service has shipped support, drop the note and replace it with a link to the Azure SignalR documentation. If support is planned, consider wording it as "not yet supported" with a tracking link instead.
  • 🟣 Should the Azure SignalR documentation carry the same warning? The natural place for a reader already on Azure SignalR is the service's own docs (/azure/azure-signalr/), which are outside this docset. Worth raising with that content team separately.
  • Finding worth noting in review: the TypeScript client, added later in #67964, already contains equivalent redirect handling — _setTransportAccessToken, the initial token lifetime captured inside _getNegotiationResponse, and adoption of an accessToken from the refresh response. So this sub-area is a .NET client catching up within the same release, not a lasting capability difference between clients. The proposed text is therefore written to describe the shipped behavior rather than as a .NET-client-only caveat, which avoids implying the TypeScript client behaves differently.
  • Deliberately not proposed: a change to xref:signalr/scale, the Azure SignalR Service article in this docset. It's the article a reader scaling out would open, but documenting a feature the service doesn't support yet would create content that's wrong the moment support ships, and stale if it doesn't. Revisit once the 🟣 above is answered.
  • Out of scope for this issue: the core authentication refresh feature (dotnet/AspNetCore.Docs#37691) and the TypeScript client APIs (tracked in a companion issue for SignalR TypeScript client supports authentication refresh).

🔗 References

Dominant language
C#
Stars
13.1k
Forks
24.6k
Avg merge
21h 10m
Merged PRs (30d)
113

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/AspNetCore.Docs

All issues in dotnet/AspNetCore.Docs

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.