我正在尝试对我的项目实施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
}
}
问题:
答案 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 集成的最直接的方法是:
为什么?
passport
实现 REST JWT 非常简单。您可以尝试按照@jkettmann 的描述在 GraphQL 中构建它,但它更复杂,支持更少。我没有看到这样做的压倒性好处。回答您的问题:
<块引用>护照主要是为 REST/Express 设计的吗?
原则上不,但你会发现大部分的资源有关REST和表达。
<块引用>这是一种普遍做法还是我应该坚持使用一些 JWT 库?
通常的做法是坚持 JWT。