GraphQL 服务器中的授权

Authorization in GraphQL servers

如何在 GraphQL 服务器中处理授权?

我应该在每个请求的身份验证 header 中传递 JWT 令牌并在 resolve() 之后检查授权用户并在每个 querymutation

简介

首先,如您所述,身份验证 的常用方法是使用包含发出请求的用户 ID 的签名 JWT。

现在让我们看看在考虑给定请求的授权时我们可以使用的不同参数

  • 谁在提出请求?

    由上述用户id决定。可以在数据库中查找有关请求者的更多信息,例如关联的用户角色。这意味着如果我们使用 SQL,我们需要维护一个 User table,并在注册时向此 table 添加新用户。

  • 应该执行哪个操作?

    用户可能被授予只读访问权限。某些变更或查询只允许某些用户使用。

  • query/mutation 响应中包含哪些字段?

    某些字段只能由某些用户访问。

权限

考虑到这些信息,我们可以想出不同的权限系统。最常见的是,在这样的系统中,默认情况下不允许进行任何操作。当一个请求进来时,可以将上面提到的参数与现有的权限进行匹配,如果找到匹配的权限,则请求被授予。

基于角色的权限

在某些应用程序中,基于角色的方法效果很好。 例如,对于 Stack Overflow 的更简单版本,我们可以使用角色 EVERYONEAUTHENTICATEDMODERATOR。一个合理的许可规则可能是这样的:

  • EVERYONE 可以阅读 questions/answers
    • 请求者:无所谓(大家)
    • 操作allQuestionsallAnswers 查询
    • 字段text

其他规则(省略参数): * AUTHENTICATED 用户可以创建新的 questions/answers * MODERATOR 用户可以创建新的 questions/answers * MODERATOR 用户可以删除 questions/answers.

现在,例如,如果收到未经身份验证的请求,请求 allQuestions 查询,那很好,因为我们找到了允许它的权限(第一个)。

另一方面,如果针对没有 MODERATOR 角色且包含 deleteQuestion 突变的用户发出经过身份验证的请求,则找不到这些参数的权限.所以请求被拒绝了。

图表权限

虽然基于角色的权限已经代表了一个可靠的权限系统,但如果我们想根据请求者和被请求节点之间的关系来授予权限,它们根本不适合。在我们的示例中,添加允许任何用户删除他们自己的 questions/answers.

的简单规则将是一项相当大的工作。

Graphcool,我们提出了一种强大但相当简单的方法,我们称之为 图形权限 来解决这个问题。让我们在检查权限时提供以下额外的参数

  • 即将访问或修改哪个节点?

    由节点id决定

然后我们可以使用 GraphQL 查询针对特殊的 权限模式 来表达权限,以在节点级别授予或拒绝权限。仅当权限查询包含至少一个不是 null.

的叶节点时,才允许访问给定节点

在我们的例子中,我们可以指定这个权限查询:

query {
  allAnswers(filter:{
      authorId: $userId,
      id: $nodeId
  }) {
    id
  }
}

对于由 GraphQL 变量 $userId$nodeId 指定的给定节点和用户,我们使用查询参数 filter 到 return 如果节点是空列表不是由当前用户创建的,或者不是由其他用户创建的。