0
votes

I have a set up of Identity Server 4, Asp.Net Core SignalR Hub, and JavaScript client. When I try to connect to the SignalR Hub, the "negotiateVersion: 1" pass correctly but the request to the hub doesn't pass at all. The error in Chrome is "HTTP Authentication failed; no valid credentials available" and 401 status code in FireFox. The id and the access token are present in the query. I try different examples but with no desired result.

Versions: Identity Server 4 - .Net Core 2.1

  • IdentityServer4.AspNetIdentity(2.5.0)

Asp.Net Core SignalR Hub - .Net Core 3.1

  • IdentityServer4.AccessTokenValidation(3.0.1)
  • Microsoft.AspNetCore.Authentication.JwtBearer(3.1.7)

JavaScript Client

  • signalr.min.js v4.2.2+97478eb6

Here is my configuration in Identity Server: Config.cs

ClientId = "my.client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes =
{
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Profile,
    "api1"
},
Claims = { },
RedirectUris = {
    "https://mySite/popupFrame.html",
    "https://mySite/silentFrame.html",
},
PostLogoutRedirectUris = {"https://mySite/logoutFrame.html" },
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
AccessTokenLifetime = (int)TimeSpan.FromMinutes(10).TotalSeconds,                

Startup.cs in ConfigureServices method

services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity<ApplicationUser>()
.AddResourceOwnerValidator<ResourceOwnerValidator>()
.AddProfileService<ProfileService>();

services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();

Here is my configuration in Asp.Net SignalR: Startup.cs in ConfigureServices method

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(options =>
    {
        options.Authority = "https://localhost:44341";
        options.RequireHttpsMetadata = false;
        options.ApiName = "api1"; 
        options.JwtBearerEvents = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                StringValues queryAccessToken = context.Request.Query["access_token"];

                PathString path = context.HttpContext.Request.Path;
                if (path.StartsWithSegments("/brokerhub") && !string.IsNullOrEmpty(queryAccessToken)) 
                {
                    context.Token = queryAccessToken;
                }
                
                return Task.CompletedTask;
            },
        };
    });

services.AddCors();
services.AddSignalR();
services.AddControllers();

Startup.cs in Configure method

app.UseRouting();

app.UseCors(builder =>
{
    builder.WithOrigins("https://mySite", "http://localhost")
        .AllowAnyHeader()
        .WithMethods("GET", "POST")
        .AllowCredentials();
});

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapHub<BrokerHub>("/brokerhub", options =>
    {
        options.Transports = HttpTransportType.WebSockets;
    });
});

The Hub controller

[Authorize]
public class BrokerHub : Hub

And finally the JS Client

client = new signalR.HubConnectionBuilder()
        .withUrl('https://hub.com/brokerhub/', {
            accessTokenFactory: () => {
                return user.access_token;
            }
        })
        .build();

Can anyone point me what I'm missing in configurations?

1
Hi, @Antonio Iliev, Does it works on Edge or IE? Try AllowedGrantTypes = GrantTypes.HybridAndClientCredentials. You could check Adding SignalR to existing IdentityServer4 AuthorizationMichael Wang
Hi @MichaelWang. Thank you for your quick response. I have the same error message in Edge and IE totally doesn't work :) . I try with the Hybrid grant type, but unfortunately, the Identity Server is throwing the "Invalid grant type for client: implicit" and refuse to authenticate the user. Thank you for the link, but the ASP.Net Core 3.1 changed the API for the services and doesn't contain the AddOpenIdConnect method anymore.Antonio Iliev

1 Answers

0
votes

Maybe this issue is relevant - https://github.com/IdentityServer/IdentityServer4/issues/2349#issuecomment-394099795

Can you please try to use options.TokenRetriever instead of OnMessageReceived as shown in the link above and introduce CustomTokenRetriever?