Token Expiry Handling with Blazor server client and Downstream APIs
Problem
In Blazor Server, communication between the browser (client) and the server is managed through SignalR, which maintains a persistent connection using WebSockets (or fallback mechanisms). Blazor Server uses SignalR for all UI interactions and event handling. The SignalR connection does not have access to HttpContext or cookies directly. When a client establishes a connection to the SignalR server it creates HubCallerContext
with ConnectionId, User (Claimsprincipal) and Items (properties).
Unlike traditional HTTP requests where cookies are sent with each request, SignalR only sends cookies once, during the initial connection (handshake). After that, no HTTP headers are included in individual method calls over SignalR.
As a result:
- You cannot access HttpContext.Request.Cookies from inside Blazor components.
- You lose access to cookies during the lifetime of the SignalR connection.
- HubCallerContext.User is not updated when the authentication cookie is renewed.
See Blazor state management Blazor Server side authentication
Alternative solution
Listen on 401 from downstream API and redirect to login site with full reload
sequenceDiagram
participant Browser as Blazor (Browser)
participant SignalR as SignalR Hub (Blazor Server)
participant API as API Backend
participant Auth as IdentityServer (Duende)
Browser->>SignalR: Establish connection (via WebSocket)
SignalR-->>Browser: Connected
Browser->>API: HTTP Request (e.g., GET /data)
API-->>Browser: JSON response
Note over Browser: Auth cookie may expire...
Browser->>API: Another request (after auth expired)
API-->>Browser: Redirect to IdentityServer
Browser->>Auth: OpenID Connect login redirect
Auth-->>Browser: Token/Cookie issued, redirected back
Browser->>SignalR: Reconnect
SignalR-->>Browser: Reconnected