0

I have a GraphQL API with mixed public and private queries and mutation. I'm looking for a way to check whether an operation requires the user to be authenticated and also a permission checker, so that the user can only modify his own data.

I noticed that the resolver function has a fourth argument, info that includes path.key which returns the name of the operation (documented here).

My solution was to add a checker function inside every resolver, like so:

// modify user details
resolve: async (parent, args, { mongo: { User }, loggedUser }, info) => {
    // auth check
    authChecker(info.path.key, loggedUser, args.id);

  // continue resolving
},

And in another file:

function authChecker(operationName, loggedUser, userId) {
  if (PUBLIC_OPERATIONS.includes(operationName) {
    // public operation
    return true;
  } else {
    // private operation
    if (args.id) {
      // private operation that requires a permission check
      ...
    } else {
      // private operation that only requires user to be logged in
      ...
    }
  }
}

The function either returns true or throws an error if conditions are not met.

I was wondering if this was an ok solution or if there was a way that this could be done with a middleware somehow so that I wouldn't have to repeat the code in every resolver. The problem is that I wouldn't have access to the operation name if I'd use a middleware. Any suggestions?

4

1 回答 1

1

应该可以使用中间件,但会很痛苦,因为您必须自己解析查询。我认为最简洁的方法是利用graphql-tools提供的模式级解析器。

const {makeExecutableSchema, addSchemaLevelResolveFunction} = require('graphql-tools')

const schema = makeExecutableSchema({typeDefs, resolvers})
addSchemaLevelResolveFunction(schema, (root, args, context, info) => {
  // check info to see if query is private and throw if user isn't authenticated
})
// use the schema like normal
app.use('/graphql', graphqlHTTP({schema}))

解析器不需要返回任何东西;它只需要在身份验证失败时抛出或返回被拒绝的 Promise。有关使用 graphql-tools 生成模式的更多信息,请查看此处的文档。

于 2017-12-08T12:39:58.847 回答