dotnet/aspnetcore · error · Error

Authentication refresh is only supported with HTTP-based…

Error message

Authentication refresh is only supported with HTTP-based connections.

What it means

Thrown by HubConnection.refreshAuthentication when `connection.features.authenticationRefresh` is undefined after the state guard passes. The feature is populated only by HTTP-based transports that implement the authenticate-refresh handshake; a custom transport or a non-HTTP connection does not advertise the feature, so manual refresh is unsupported.

Solutions

  1. Use the standard HttpConnection (withUrl) which wires the authenticationRefresh feature when the server supports it.
  2. If using a custom transport, implement and attach `features.authenticationRefresh = { refreshAuthentication, initialTokenLifetimeInSeconds }`.
  3. Guard the call with a check that the feature exists before invoking refresh.

Example fix

// before
await hubConnection.refreshAuthentication(); // custom transport
// after - guard the feature
const feat = (hubConnection as any).connection?.features?.authenticationRefresh;
if (feat) await hubConnection.refreshAuthentication();
Defensive patterns

Strategy: type-guard

Validate before calling

function supportsAuthRefresh(features: any): boolean {
  return !!features?.authenticationRefresh?.refreshAuthentication;
}

Type guard

function hasAuthRefreshFeature(f: any): f is { refreshAuthentication: () => Promise<number|undefined>; initialTokenLifetimeInSeconds?: number } {
  return !!f && typeof f.refreshAuthentication === "function";
}

Prevention

When it happens

Trigger: Calling refreshAuthentication on a HubConnection whose underlying connection was built with a custom IHttpConnectionOptions/transport that does not set `features.authenticationRefresh`, or using a connection type that does not implement the IAuthenticationRefreshFeature contract.

Common situations: Injecting a mock/in-memory transport for testing, using an older transport adapter, or building a custom transport that omits the authenticationRefresh feature.

Understand the failure class

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/29bf11ad972ce250. Report an issue: GitHub.

Appendix: source

Thrown at src/SignalR/clients/ts/signalr/src/HubConnection.ts:625

     */
    public onreconnected(callback: (connectionId?: string) => void): void {
        if (callback) {
            this._reconnectedCallbacks.push(callback);
        }
    }

    /** Refreshes the authentication state for this connection.
     *
     * @returns A Promise that resolves with the new server-reported token lifetime in seconds, or undefined when the server does not report one.
     */
    public async refreshAuthentication(): Promise<number | undefined> {
        if (this._connectionState !== HubConnectionState.Connected) {
            throw new Error("Cannot refresh authentication when the connection is not active.");
        }

        const authenticationRefreshFeature = this.connection.features.authenticationRefresh as IAuthenticationRefreshFeature | undefined;
        if (!authenticationRefreshFeature) {
            throw new Error("Authentication refresh is only supported with HTTP-based connections.");
        }

        let newTokenLifetimeInSeconds: number | undefined;
        try {
            newTokenLifetimeInSeconds = await authenticationRefreshFeature.refreshAuthentication();
        } catch (e) {
            await this._invokeAuthenticationRefreshFailed(e);
            throw e;
        }

        if (this._connectionState === HubConnectionState.Connected &&
            this.connection.features.authenticationRefresh === authenticationRefreshFeature &&
            this._isAutoAuthenticationRefreshEnabled() &&
            isValidAuthenticationTokenLifetime(newTokenLifetimeInSeconds)) {
            this._scheduleAuthenticationRefresh(newTokenLifetimeInSeconds);
        }

        await this._invokeAuthenticationRefreshed(newTokenLifetimeInSeconds);

View on GitHub (pinned to 3600ca084e)