使用 express js、passport s 保护 GraphQL 查询

Posted

技术标签:

【中文标题】使用 express js、passport s 保护 GraphQL 查询【英文标题】:Secure GraphQL queries with express js, passport s 【发布时间】:2017-08-10 16:35:21 【问题描述】:

我已经开始在我的 express js 项目中使用 graphql,但我想知道如何保护我的一些 GraphQL 查询。 以前我为此使用了护照 js(JWT),效果很好。保护路线真的很容易,但是使用 graphql(express-graphql) 我找不到任何解决方案。 此外,最好有某种基于角色的解决方案来保护特定领域。有什么好的教程如何保护 graphQL 吗?

【问题讨论】:

【参考方案1】:

最后我检查了那里没有任何真正好的教程来展示如何保护 GraphQL 端点。但是,社区(GraphQL 和 Apollo 松弛通道)的共识是,最好将身份验证与 GraphQL 分开(例如使用 Passport)并在您的解析函数中进行授权,可能通过使用一些基于角色的身份验证来装饰它们。

目前我可以提供的最佳链接是this post 我不久前写过关于使用 Passport.js 为 GraphQL 端点设置身份验证的文章。希望对你有帮助!

我目前正在使用 Apollo 编写 React + Node.js 的全栈 GraphQL 教程,我计划为此做一些关于 Auth 的工作。我会在发布后尽快更新此答案。

【讨论】:

【参考方案2】:

我目前正在评估通过 express、passport 和 jwt 对解析器进行授权的潜力。它尚未经过全面测试,但可以正常工作。

为此,您至少需要在上下文中传递请求:

const graphql = graphqlExpress((req, res) => 
  return (
    schema,
    rootValue: resolver,
    // For query authorization. Ideally, Passport will handle all requests and authenticate
    // each one for the current user. The queries will fetch data exclusively related to that user.
    context:  req, res ,
  );
);
// The api
app.use('/api', graphql);

在这种情况下,我承诺了护照认证:

const auth = (req, res) => new Promise((resolve, reject) => 
  passport.authenticate('jwt',  session: false , (err, user) => 
    if (err) reject(err);
    if (user) resolve(user);
    else reject('Unauthorized');
  )(req, res);
);

const resolver = 
  users: (root, ctx) => auth(ctx.req, ctx.res)
    .then(() => User.find(, (err, res) => res))
    .catch((err) => 
      throw new Error(err);
    ),
;

由于没有太多关于如何涵盖这一点的示例,我一直在努力让它变得简单,但我认为我做得很好。

这里是我用来达到这一点的资源:

how to get passport.authenticate local strategy working with async/await pattern https://matoski.com/article/jwt-express-node-mongoose/ https://dev-blog.apollodata.com/auth-in-graphql-part-2-c6441bcc4302

【讨论】:

ElPepe 干得好,大多数帖子都以更清晰的方式做到这一点 这正是我想要的。非常感谢!【参考方案3】:

为了纠正错误,我修改了如下代码。

const getUser = (req: Express.Request, res: Express.Response) => 
  new Promise((resolve, reject) => 
    passport.authenticate('jwt', session: false, (err, payload, info) => 
      if (err) reject(info)
      if (payload) resolve(payload)
      else reject(info)
    )(req, res)   
)


const getApolloServer = async () => 
  return new ApolloServer(
    schema: await buildSchema(
      resolvers: [] // Your resolvers
    ),
    context: async ( req, res ) => 
      try 
          const user = await getUser(req, res)
          return  user 
         catch(err: any) 
          console.log(err)
          res.status(401).json(err.message)
        
     ,
     introspection: true,
     playground: true,
   )

【讨论】:

以上是关于使用 express js、passport s 保护 GraphQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

使用 Passport.js、express-session 和 express-mysql-session 进行用户身份验证

Express + Passport.js:req.user 未定义

用户注册时出错(Express.Js、Passport、MySQL)

使用 passport.js、mysql 和 express-session 保持登录状态

logout() 在使用 passport.js、express.js、AngularJs 时不起作用

无法使用 Passport.js 和 Express 4 访问 req.user