【发布时间】:2022-01-21 13:48:46
【问题描述】:
我正在尝试使用 SignalR 为 Blazor WASM 应用程序实现身份验证例程,但基本上是碰壁了。
我已经启动并运行了一个外部 Keycloak 服务器,并且 WASM 应用程序正在成功地针对该服务器进行身份验证;客户端实际上正在获得一个有效的 JWT 令牌等等。当我尝试让 SignalR Hub 和客户端进行身份验证时,我遇到了问题。不过,只要我不将[Authenticate] 添加到集线器,就会建立连接。
根据官方文档,这就是我应该让客户端连接到集线器的方式:
hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/chathub"), options =>
{
options.AccessTokenProvider = () => Task.FromResult(_accessToken);
})
.Build();
在 SignalR Hub 上,我应该这样做:
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 设置。
【问题讨论】:
-
令牌在第一次请求期间位于标头中。
-
哦,是的,就是这样。嗯。不会改变它仍然产生 401 的事实。
-
您需要配置中间件以将令牌添加到中心请求。
-
太棒了。究竟是哪个“中间件”?我在这里使用这些文档:docs.microsoft.com/en-us/aspnet/core/signalr/…
标签: jwt signalr blazor openid-connect webassembly