如何在graphql中使用本地护照

时间:2019-08-17 19:29:32

标签: graphql passport.js apollo-server passport-local

我正在尝试对我的项目实施GraphQL,我想在我的登录Mutation中使用passport.authenticate('local')

我想要的代码修改:

const typeDefs = gql`
type Mutation {
      login(userInfo: UserInfo!): User
    }
`

 const resolvers = {
    Mutation: {
      login: (parent, args) => { 
        passport.authenticate('local')
        return req.user
    }
}

问题:

  1. 密码主要是针对REST / Express设计的吗?
  2. 我可以操纵passport.authenticate方法(向其传递用户名和密码)吗?
  3. 这是否是常见的做法,还是我应该坚持使用一些JWT库?

3 个答案:

答案 0 :(得分:1)

Passport.js是“与Express兼容的身份验证中间件”。 authenticate返回Express中间件功能-旨在防止对特定Express路由的未授权访问。它不太适合在解析器内部使用。如果通过上下文将req对象传递给解析器,则可以调用req.login手动登录用户,但是在传递之前必须验证凭据并自己创建user对象它的功能。同样,您可以调用req.logout手动注销用户。有关文档,请参见here

如果您想使用Passport.js,最好的做法是为您正在使用的每个标识提供程序创建一个具有授权路由和回调路由的Express应用程序(有关示例,请参见this) 。然后使用apollo-server-express将Express应用程序与您的GraphQL服务集成。您的客户端应用程序将使用授权路由来初始化身份验证流程,并且回调端点将重定向回您的客户端应用程序。然后,您可以将req.user添加到上下文中,并在解析器,指令,GraphQL中间件等内部进行检查。

但是,如果您仅使用本地策略,则可以考虑完全放弃Passport并自行处理。

答案 1 :(得分:1)

我花了一些时间将自己的头包裹在GraphQL和Passport的结合上。尤其是当您希望将本地策略与登录突变一起使用时,会使生活变得复杂。这就是为什么我创建了一个名为graphql-passport的小npm包的原因。

这是服务器设置的样子。

import express from 'express';
import session from 'express-session';
import { ApolloServer } from 'apollo-server-express';
import passport from 'passport';
import { GraphQLLocalStrategy, buildContext } from 'graphql-passport';

passport.use(
  new GraphQLLocalStrategy((email, password, done) => {
    // Adjust this callback to your needs
    const users = User.getUsers();
    const matchingUser = users.find(user => email === user.email && password === user.password);
    const error = matchingUser ? null : new Error('no matching user');
    done(error, matchingUser);
  }),
);

const app = express();
app.use(session(options)); // optional
app.use(passport.initialize());
app.use(passport.session()); // if session is used

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req, res }) => buildContext({ req, res, User }),
});

server.applyMiddleware({ app, cors: false });

app.listen({ port: PORT }, () => {
  console.log(`? Server ready at http://localhost:${PORT}${server.graphqlPath}`);
});

现在,您将可以通过GraphQL上下文访问护照专用功能和用户。这是您编写解析器的方式:

const resolvers = {
  Query: {
    currentUser: (parent, args, context) => context.getUser(),
  },
  Mutation: {
    login: async (parent, { email, password }, context) => {
      // instead of email you can pass username as well
      const { user } = await context.authenticate('graphql-local', { email, password });

      // only required if express-session is used
      context.login(user);

      return { user }
    },
  },
};

结合使用GraphQL和Passport.js是有意义的。特别是如果您想添加更多的身份验证提供程序,例如Facebook,Google等。如果需要,您可以找到更详细的信息in this blog post

答案 2 :(得分:0)

除非您的目标是深入了解身份验证,否则您绝对应该使用 passport

我发现将 passport 与 GraphQL 集成的最直接的方法是:

  • 使用 JWT 策略
  • 保留 REST 端点以验证和检索令牌
  • 将令牌发送到 GraphQL 端点并在后端对其进行验证

为什么?

  • 如果您使用的是客户端应用,无论如何,基于令牌的身份验证都是最佳做法。
  • 使用 passport 实现 REST JWT 非常简单。您可以尝试按照@jkettmann 的描述在 GraphQL 中构建它,但它更复杂,支持更少。我没有看到这样做的压倒性好处。
  • 在 GraphQL 中实现 JWT 很简单。见例如expressNestJS

回答您的问题:

<块引用>

护照主要是为 REST/Express 设计的吗?

原则上不,但你会发现大部分的资源有关REST和表达。

<块引用>

这是一种普遍做法还是我应该坚持使用一些 JWT 库?

通常的做法是坚持 JWT。