[release/11.0-preview6] Add SignalR Auth Refresh support to server and .NET client - #67400
Merged
wtgodbe merged 1 commit intoJun 24, 2026
Conversation
Server-side: - Add /refresh HTTP endpoint mapped alongside /negotiate - Add tokenLifetimeSeconds to negotiate response (NegotiationResponse + NegotiateProtocol) - Server re-authenticates on /refresh and updates connection's User and auth expiration - Compute TTL from AuthenticationProperties.ExpiresUtc - New virtual Hub.OnAuthRefreshedAsync() lifecycle hook .NET Client-side: - Add IAuthRefreshFeature interface in Connections.Abstractions - HttpConnection implements IAuthRefreshFeature, POSTs to /refresh endpoint - HubConnection.RefreshAuthAsync() discovers IAuthRefreshFeature via Features collection - Auto-refresh timer schedules at: now + TTL - RefreshBeforeExpiration (default 5 min) (cherry picked from commit 8835dfc)
Contributor
There was a problem hiding this comment.
Pull request overview
Backports SignalR authentication refresh support to release/11.0-preview6, enabling clients to refresh credentials for an active connection (via a new /refresh endpoint) and allowing hub/user state to be updated without a reconnect.
Changes:
- Server: adds
/refreshendpoint + negotiate metadata (tokenLifetimeSeconds), updates connection principal/expiration, and introducesHub.OnAuthenticationRefreshedAsync(). - Server hub pipeline: snapshots
HubCallerContext.Userper invocation to keep in-flight hub calls consistent across refreshes. - .NET client: adds auth-refresh feature interface +
HubConnection.RefreshAuthenticationAsync()and auto-refresh scheduling based on server TTL.
Show a summary per file
| File | Description |
|---|---|
| src/SignalR/server/StackExchangeRedis/src/RedisHubLifetimeManager.cs | Passes explicit userIdentifier into user subscription/removal helpers (stabilizes channel selection). |
| src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests/MapSignalRTests.cs | Verifies auth metadata is applied to the new /refresh endpoint. |
| src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.AuthenticationRefresh.cs | New hub-layer tests covering user refresh behavior, serialization, and abort semantics. |
| src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests/DefaultHubLifetimeManagerTests.cs | Minor whitespace change. |
| src/SignalR/server/Core/src/PublicAPI.Unshipped.txt | Records new virtual Hub.OnAuthenticationRefreshedAsync() API. |
| src/SignalR/server/Core/src/Internal/SignalRServerActivitySource.cs | Adds activity name for auth refresh lifecycle hook. |
| src/SignalR/server/Core/src/Internal/HubDispatcher.cs | Extends dispatcher contract with OnAuthenticationRefreshedAsync. |
| src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs | Invokes OnAuthenticationRefreshedAsync, snapshots caller context, and traces/logs refresh hook failures. |
| src/SignalR/server/Core/src/Internal/DefaultHubCallerContext.cs | Changes caller context to snapshot User rather than reading from live connection state. |
| src/SignalR/server/Core/src/HubConnectionHandlerLog.cs | Adds logs for user identifier changes and refresh application errors. |
| src/SignalR/server/Core/src/HubConnectionHandler.cs | Subscribes to user-refresh feature and applies refreshed user state / dispatches hub refresh hook. |
| src/SignalR/server/Core/src/HubConnectionContext.cs | Adds refresh-aware user/id handling and publishes updated HubCallerContext on refresh. |
| src/SignalR/server/Core/src/Hub.cs | Introduces overridable OnAuthenticationRefreshedAsync() lifecycle method. |
| src/SignalR/samples/JwtClientSample/Program.cs | Updates sample to use new client auth-refresh support. |
| src/SignalR/common/Http.Connections/test/NegotiateProtocolTests.cs | Adds tests for tokenLifetimeSeconds negotiate serialization/parsing. |
| src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs | Adds endpoint routing tests for refresh endpoint registration/metadata. |
| src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs | Makes test class partial for auth-refresh test split. |
| src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.AuthenticationRefresh.cs | New dispatcher tests for /refresh, TTL, callback accept/reject, and poll/reconnect behavior. |
| src/SignalR/common/Http.Connections/src/PublicAPI.Unshipped.txt | Adds public API entries for refresh options/context/metadata. |
| src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.Log.cs | Adds log for refresh rejection by callback. |
| src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs | Implements /refresh endpoint, TTL computation, and refresh-aware principal handling on poll/reconnect. |
| src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs | Adds user-refresh feature, atomic UpdateUser, and callback dispatch. |
| src/SignalR/common/Http.Connections/src/HttpConnectionDispatcherOptions.cs | Adds EnableAuthenticationRefresh + OnAuthenticationRefresh and modernizes some option properties. |
| src/SignalR/common/Http.Connections/src/ConnectionEndpointRouteBuilderExtensions.cs | Maps the /refresh endpoint alongside /negotiate when enabled. |
| src/SignalR/common/Http.Connections/src/AuthenticationRefreshMetadata.cs | New endpoint metadata marker type for /refresh. |
| src/SignalR/common/Http.Connections/src/AuthenticationRefreshContext.cs | New callback context for refresh accept/reject policy. |
| src/SignalR/common/Http.Connections.Common/src/PublicAPI.Unshipped.txt | Adds NegotiationResponse.TokenLifetime public API. |
| src/SignalR/common/Http.Connections.Common/src/NegotiationResponse.cs | Carries server-reported token lifetime on negotiate. |
| src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs | Serializes/parses tokenLifetimeSeconds. |
| src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/AccessTokenHttpMessageHandler.cs | Forces fresh token for refresh requests and only commits it to cache on success. |
| src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnection.cs | Implements auth-refresh feature and posts to /refresh, parsing TTL from response. |
| src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.AuthenticationRefresh.cs | New unit tests for HubConnection refresh API and auto-refresh scheduling. |
| src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionTests.AuthenticationRefresh.cs | New unit tests for refresh request behavior and access-token caching semantics. |
| src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs | Adds auth-refresh hub + JWT token generator with optional scope claim. |
| src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs | Adds AuthenticationRefreshHub used by functional tests. |
| src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs | Adds clarifying comment for header-based user id provider test. |
| src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.AuthenticationRefresh.cs | New functional tests for refresh behavior across transports and reconnect scenarios. |
| src/SignalR/clients/csharp/Client/test/FunctionalTests/HeaderUserIdProvider.cs | Prefers authenticated NameIdentifier so refresh can change derived user id. |
| src/SignalR/clients/csharp/Client.Core/src/PublicAPI.Unshipped.txt | Adds public APIs for refresh options + HubConnection.RefreshAuthenticationAsync. |
| src/SignalR/clients/csharp/Client.Core/src/HubConnectionBuilderExtensions.cs | Adds WithAuthenticationRefresh(...) builder extension. |
| src/SignalR/clients/csharp/Client.Core/src/HubConnection.Log.cs | Adds log events for refresh start/completion/failure and callback failures. |
| src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs | Implements refresh API + timer-based auto-refresh scheduling. |
| src/SignalR/clients/csharp/Client.Core/src/AuthenticationRefreshOptions.cs | New options + callback contexts for refresh. |
| src/Servers/Connections.Abstractions/src/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt | Adds new connection feature APIs for auth refresh + user refresh notifications. |
| src/Servers/Connections.Abstractions/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt | Adds new connection feature APIs for auth refresh + user refresh notifications. |
| src/Servers/Connections.Abstractions/src/PublicAPI/net462/PublicAPI.Unshipped.txt | Adds new connection feature APIs for auth refresh + user refresh notifications. |
| src/Servers/Connections.Abstractions/src/PublicAPI/net11.0/PublicAPI.Unshipped.txt | Adds new connection feature APIs for auth refresh + user refresh notifications. |
| src/Servers/Connections.Abstractions/src/PublicAPI/net10.0/PublicAPI.Unshipped.txt | Adds new connection feature APIs for auth refresh + user refresh notifications. |
| src/Servers/Connections.Abstractions/src/Features/IConnectionUserRefreshFeature.cs | New feature interface for observing refreshed connection user. |
| src/Servers/Connections.Abstractions/src/Features/IAuthenticationRefreshFeature.cs | New feature interface for initiating auth refresh + exposing initial TTL. |
Copilot's findings
- Files reviewed: 50/50 changed files
- Comments generated: 2
Comment on lines
+578
to
+584
| public async Task<TimeSpan?> RefreshAuthenticationAsync(CancellationToken cancellationToken = default) | ||
| { | ||
| var connectionState = _state.CurrentConnectionStateUnsynchronized; | ||
| if (connectionState == null) | ||
| { | ||
| throw new InvalidOperationException("Cannot refresh authentication when the connection is not active."); | ||
| } |
Comment on lines
+650
to
+654
| if (tokenLifetime <= new TimeSpan(refreshBefore.Ticks * 2)) | ||
| { | ||
| // Short-lived token: refresh at half the TTL to avoid spamming | ||
| refreshIn = new TimeSpan(tokenLifetime.Ticks / 2); | ||
| } |
This was referenced Jun 24, 2026
wtgodbe
approved these changes
Jun 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backport of #67111 to
release/11.0-preview6.Cherry-picked from 8835dfc (clean, no conflicts).
Description
Adds SignalR Auth Refresh support to the server and .NET client.
Server-side:
/refreshHTTP endpoint mapped alongside/negotiatetokenLifetimeSecondsto negotiate response (NegotiationResponse + NegotiateProtocol)/refreshand updates connection's User and auth expirationAuthenticationProperties.ExpiresUtcHub.OnAuthRefreshedAsync()lifecycle hook.NET Client-side:
IAuthRefreshFeatureinterface in Connections.AbstractionsHttpConnectionimplementsIAuthRefreshFeature, POSTs to/refreshendpointHubConnection.RefreshAuthAsync()discoversIAuthRefreshFeaturevia Features collectionVerification
HubConnectionHandlerTests.AuthenticationRefreshand clientHttpConnection/HubConnectionauth-refresh unit tests pass locally./cc @BrennanConroy