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?
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials
. You could check Adding SignalR to existing IdentityServer4 Authorization – Michael Wang