使用Identity Server 4的SignalR强调失败

问题描述

我设置了Identity Server 4,Asp.Net Core SignalR Hub和JavaScript客户端。 当我尝试连接到SignalR集线器时,“ negotiateVersion:1”正确传递,但对集线器的请求根本没有传递。 Chrome中的错误是“ HTTP身份验证失败;没有有效的凭据可用”和FireFox中的401状态代码。 ID和访问令牌出现在查询中。我尝试了不同的示例,但没有理想的结果。

版本: Identity Server 4-.Net Core 2.1

  • IdentityServer4.AspNetIdentity(2.5.0)

Asp.Net Core SignalR集线器-.Net Core 3.1

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

JavaScript客户端

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

这是我在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,

ConfigureServices方法中的Startup.cs

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

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

这是我在Asp.Net SignalR中的配置: ConfigureServices方法中的Startup.cs

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();

Configure方法中的Startup.cs

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;
    });
});

集线器控制器

[Authorize]
public class brokerHub : Hub

最后是JS Client

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

有人可以指出我在配置中缺少什么吗?

解决方法

也许这个问题是相关的-https://github.com/IdentityServer/IdentityServer4/issues/2349#issuecomment-394099795

您能否尝试使用 options.TokenRetriever 代替上面链接中所示的 OnMessageReceived 并引入CustomTokenRetriever?