如何为Apollo的变体实施auth指令?

时间:2019-01-02 10:19:14

标签: javascript authentication graphql apollo apollo-server

我正在尝试为我正在处理的项目设置Apollo后端,在该项目中尝试实现架构指令。但是,我无法将我的架构指令添加到突变中。因此,我的主要问题是:如何为突变实现auth指令?

我在用户查询的末尾添加了@auth(requires: ADMIN),一切正常。然后,Apollo将需要具有管理员访问权限的承载令牌才能执行用户查询。

extend type Query {
    user(id: ID!): User
    users: [User!]! @auth(requires: ADMIN)
}

当我尝试以相同的方式对editMyUser突变进行操作时,似乎对所有突变都执行了auth指令,而不仅仅是我想要的突变。当我将@auth部分添加到editMyUser突变中时,即使signUp突变也将给出“未授权”错误。即使它们之间没有关系。

应该在调用时传递给auth指令的角色字段退出为空。

extend type Mutation {
    signUp(
        username: String!
        firstName: String
        lastName: String
        password: String!
        isAdmin: Boolean
        isActive: Boolean): User!
    login(
        username: String!
        password: String!): User!
    editMyUser(
        id: ID!
        firstName: String
        lastName: String
        password: String): User! @auth(requires: USER)
    adminEditUser(
        id: ID!
        firstName: String
        lastName: String
        password: String
        isActive: Boolean
        isAdmin: Boolean
        isBanned: Boolean): User!
}

这就是我实现模式指令的方式

export default gql`
directive @auth(requires: Role = ADMIN) on OBJECT | FIELD_DEFINITION

enum Role {
    ADMIN
    USER
}

https://github.com/jwhenshaw/graphql-directives-auth 这是我在代码中实现的Auth指令,以供参考。

总而言之,当我为突变实现auth指令时,它们针对所有突变而不是仅针对一个突变而实现,并且由于角色没有传递给该指令,它甚至无法正常工作。

我很想得到一些帮助。谢谢!

2 个答案:

答案 0 :(得分:3)

在该仓库中,AuthDirective类将被包装在objectType方法中的字段的ensureFieldWrapped传递。这意味着在您的示例中,您将指令直接分配到editMyUser对象上的字段Mutation上,该方法将Mutation的所有子代包装起来(我相信实际上,您的查询也应如此。

因此,在示例存储库中,这很好,因为我们有一个对象类型User,并且包装了它及其字段。但是,如果您不希望这样做,可以更改AuthDirective类以仅包装其所在的字段。

我已完成此操作并将其推送到仓库https://github.com/jwhenshaw/graphql-directives-auth,您可以在此处看到FieldAuthDirectiveObjectAuthDirective。我仍然需要稍微清理一下代码,但是推送了一个有效的示例,并留下了一些日志来帮助突出这些差异。如果您不希望在本地运行它,可以在https://qzj70qn2mj.sse.codesandbox.io/处查看。

希望这会有所帮助,让我知道是否需要详细说明。

答案 1 :(得分:1)

这里的问题是,当包装解析器未在these lines of code中找到任何必需的角色(对象类型和相关字段均未使用)时,引用的实现将引发错误。

逻辑是,当您将指令用于对象类型的某些字段时,还需要提供类型本身的要求。我认为这种逻辑还不错,正如代码注释所建议的那样是安全的。该实现的作者可能专注于将指令用于实际数据类型,而不是用于查询或变异。

让我更具体一点:当您将指令用于一个或多个查询/更改时,您和我所做的事情(因为我正在努力完成与您今天相同的事情)实际上是在模式QueryMutation的字段。因此,如果我们不希望对架构的所有查询和/或更改都具有最低要求,则代码不应在我上面链接的那种情况下引发错误,而应像满足要求一样调用包装的解析程序(因为没有)。

示例:

if (!requiredRole) {
  // No auth required, just call the resolver
  return resolve.apply(this, args);
}

我希望这会有所帮助!