[英]Set http only cookie from resolver in apollo graphql
我正在尝试将res
从我的上下文传递到解析器,以便我可以在我的登录 function 中调用context.res.cookie
,然后发送一个 http only cookie。 我有以下代码,我没有在客户端上看到添加的 cookie,但 function 中的登录除此之外还在工作:
const resolvers = {
Mutation: {
signin: async (_, { email, password }, context) => {
const user = await User.findOne({ email: email });
if (!user) {
throw new Error("No such user found");
}
const valid = bcrypt.compare(password, user.password);
if (!valid) {
throw new Error("Invalid password");
}
const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET,
{
expiresIn: "30m",
});
context.res.cookie("token", token, {
httpOnly: true,
secure: true,
maxAge: 8600,
});
return {
token,
user,
};
},
},
};
我已经缩短了上面的代码,但最初我返回的是 JWT 令牌和 mongodb 用户,我还尝试添加相同令牌的 http cookie(稍后当我单独访问和刷新令牌时它将是一个不同的令牌)。
const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req, res }) => {
/* Authentication boiler plate */
return { isAuthenticated, res };
},
});
上面的代码就是我传递 res 的方式,不确定是否需要它,但以防万一。
以下是如何从前端调用 function:
export const Login = () => {
const SIGN_IN = gql`
mutation Signin($email: String!, $password: String!) {
signin(email: $email, password: $password) {
token
user {
id
name
email
}
}
}
`;
const [signIn, { error, loading, data }] = useMutation(SIGN_IN);
const signInFunction = async () => {
signIn({
variables: {
email: email,
password: password,
},
});
};
if (data) {
return <Navigate to="/" />
}
};
所以我需要稍微改变我的客户端和服务器来解决我的问题。 在 apollo-client 的客户端上,我需要将我的 apolloClient 更改为:
const apolloClient = new ApolloClient({
uri: "http://localhost:3001/graphql",
cache: new InMemoryCache(),
});
对此:
const apolloClient = new ApolloClient({
uri: "http://localhost:3001/graphql",
cache: new InMemoryCache(),
credentials: "include",
});
现在在服务器上我需要像这样添加 cors:
const server = new ApolloServer({
typeDefs,
resolvers,
cors: {
origin: "http://localhost:3000",
credentials: true,
},
context: async ({ req, res }) => {
/* insert any boilerplate context code here */
return { isAuthenticated, res };
},
});
因此,以这种方式将 res 传递给解析器非常有效。 但是,当我现在从服务器获取 cookie 时,如果我刷新页面,它会被删除,因此我需要一个明确的到期日期,因此我将 cookie 更改为:
context.res.cookie("token", token, {
httpOnly: true,
secure: true,
maxAge: 8600,
});
至(24 小时到期):
context.res.cookie("token", token, {
httpOnly: true,
secure: true,
expires: new Date(Date.now() + 24 * 60 * 60 * 1000),
});
关于此解决方案的一些注意事项:在客户端上,当您添加credentials: "include"
,您还需要在后端添加 cors,否则将无法正常工作,但是,如果您删除这两个凭据,它们将在没有 cookies 的情况下正常通信。另外,如果您添加 cors 而不是 include 什么都不会中断,但您不会收到 cookies。
最后这篇文章帮助我找到了解决方案,但是我不需要设置 express 中间件或使用apollo-link-http
库,正如您在我的解决方案中看到的那样,但是这篇文章可能仍然有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.