首页 > 解决方案 > 在 Azure Function 中使用 JWT 进行无服务器 SignalR 身份验证

问题描述

SignalRConnectionInfo在 Azure 函数中使用输入绑定。在此绑定中,我需要提供userId当前主体的,但默认情况下,Azure 函数仅支持使用来自应用服务身份验证的预定义标头,如此处所述以及以下示例:

[FunctionName("negotiate")]
public static SignalRConnectionInfo Negotiate(
  [HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req, 
  [SignalRConnectionInfo(HubName = "foo", UserId = "{headers.x-ms-client-principal-id}")] SignalRConnectionInfo connectionInfo)
{
  return connectionInfo;
}

由于我没有使用 App Service 身份验证,也不希望这样做,这不适合我的需要。

我目前拥有的是一个 JWT,用户将它提供给我们在另一个应用服务中托管的 API,以便对请求进行身份验证并识别自己。如何修改绑定的UserId属性SignalRConnectionInfo以从该 JWT 中的声明中检索 UserId?

标签: signalrazure-functions

解决方案


AFAIK 没有办法使用绑定表达式从 JWT 中提取信息。

相反,您必须使用运行时绑定首先从 JWT 中提取信息,然后在绑定中使用它来获取 SignalR 连接信息。

这是一个功能示例,其中 JWT 从Authorization标头中检索、验证,然后应用于SignalRConnectionInfo属性。

[FunctionName("Negotiate")]
public static async Task<IActionResult> Run(
  [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "negotiate")] HttpRequest req,
  IBinder binder)
{
  if (req.Headers.ContainsKey("Authorization"))
  {
    var principal = TryGetPrincipal(req.Headers["Authorization"].ToString());
    if (principal != null) 
    {
      var connectionInfo = await binder.BindAsync<SignalRConnectionInfo>(new SignalRConnectionInfoAttribute
      {
        HubName = _hubName,
        UserId = principal.FindFirst(ClaimTypes.NameIdentifier).Value
      });
      return new OkObjectResult(connectionInfo);
    }
  }

  return new UnauthorizedResult();
}

public ClaimsPrincipal TryGetPrincipal(string token) {
  // implementation varies based on authorization type...
}

推荐阅读