Blazor WebAssembly SignalR身份验证在协商时未通过AccessToken



我正在尝试使用SignalR为Blazor WASM应用程序实现身份验证例程,并基本上运行到墙上。

我已经启动并运行了一个外部Key斗篷服务器,WASM应用程序正在成功地对该服务器进行身份验证;客户端实际上得到了一个有效的JWT令牌等等。当我试图让SignalR Hub和客户端进行身份验证时,我遇到了问题。不过,只要我不将[Authenticate]添加到集线器,就可以建立连接。

根据官方文档,这就是我应该让客户端连接到集线器的方式:

hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/chathub"), options =>
{
options.AccessTokenProvider = () => Task.FromResult(_accessToken);
})
.Build();

在SignalR集线器上,我应该这样做:

builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "https://keycloak/auth/realms/master/";
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/chathub")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});

我在客户端上得到的只是控制台上的一个带有大401(即"未授权"(的错误我能够在应用程序中添加一个自定义的授权例程(它只是为每次授权尝试返回"成功"(,并找到了问题的可能根源:

客户端对集线器进行两次连接尝试。第一个是到/chathub/negotiate?negotiateVersion=1,第二个是到/chathub

但是,只有第二个请求携带access_token!因此,使用上述代码将在第一步中断,因为在协商阶段似乎已经需要access_token,而HubConnectionBuilder由于某种原因没有提供该参数。

我做错了什么?

编辑:见下面的答案。问题不是缺少令牌,而是缺少options.Audience设置。

好吧,我终于找到了问题和解决方案。我对令牌验证默默失败的事实感到恼火,然后仔细查看了处理令牌的中间件。我注意到它基本上覆盖了一个事件处理程序,并问自己是否有其他事件处理程序?

好吧,你瞧,像这样添加OnAuthenticationFailed并在返回中设置断点,让我看到了实际的错误消息:

options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/chathub")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
}
};

其声明CCD_ 8属性为空。我现在所要做的就是将正确的映射添加到我的Key斗篷服务器(请参阅这个StackOverflow线程(,并将options.Audience = "ClientId"添加到如下配置中:

builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "https://keycloak/auth/realms/master";
options.Audience = "ClientID";
options.Events = new JwtBearerEvents
{
[...]

相关内容

  • 没有找到相关文章

最新更新