If you ever worked with SignalR and IdentityServer4, you probably did some “googling” around to figure how the heck JWT authentication works.

Especially since, the token might not be anymore in the request’s ‘Authentication’ attribute, and with SignalR’s preference to WebSocket and fallback transport options.

Maybe you found a lot of answers, maybe not.

In any case, the simplest one I have come across with is the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(options =>
    {
        // base-address of your identityserver
        options.Authority = Configuration["IdentityServer:Url"];

        // name of the API resource
        options.ApiName = Configuration["IdentityServer:APIName"];
        options.ApiSecret = Configuration["IdentityServer:APISecret"];

        options.EnableCaching = true;
        options.CacheDuration = TimeSpan.FromMinutes(10); // that's the default

        options.RequireHttpsMetadata = Convert.ToBoolean(Configuration["IdentityServer:RequireHttpsMetadata"]);

        // For SignalR
        options.TokenRetriever = new Func<HttpRequest, string>(req =>
        {
            var fromHeader = TokenRetrieval.FromAuthorizationHeader();
            var fromQuery = TokenRetrieval.FromQueryString();
            return fromHeader(req) ?? fromQuery(req);
        });
    }

The snippet is originally from here and has been slighlty modified to my use-case.

Pay attention to lines 17-22 where TokenRetriever is specified to get the token either from the Header or the Query (also based on client-side implementation of SignalR).

PS: This works as intended with ASP.NET Core 3.0