Cookie doesn't set when deploy in server [Heroku] with Apollo GraphQL #4848
-
Hello, everyone I have some problem that cookies that i send in token handler is not set when deployed in heroku but it works fine when development which in localhost, I was read many documentation and cant get it. For example mutation signin : signin: async (
_: any,
{ credentials }: SignInArgs,
{ db, res }: Context
): Promise<UserPayloadType> => {
const { email, password } = credentials;
// compare input form email with data in database avaliable or not
const user = await db.user.findUnique({
where: {
email,
},
});
if (!user) {
return {
userErrors: [
{
message: "Can't find user with this email",
},
],
};
}
if (user.isVerified === false) {
return {
userErrors: [
{
message: "Please verified your account first",
},
],
};
}
// compare and force override user.password as string
const isMatch = await bcrypt.compare(password, user.password as string);
if (!isMatch) {
return {
userErrors: [
{
message: "Your password does not match",
},
],
};
}
// create token to cookie
const authToken = createToken(user.id, user.username);
// and send it
sendToken(res, authToken);
return {
userErrors: [],
user: user,
};
}, This is my backend server import { typeDefs } from "./graphql/schema";
import { AllResolvers } from "./services/resolvers/resolvers";
import { createServer } from "http";
import { execute, subscribe } from "graphql";
import { SubscriptionServer } from "subscriptions-transport-ws";
import { makeExecutableSchema } from "@graphql-tools/schema";
import { ApolloServerPluginLandingPageGraphQLPlayground } from "apollo-server-core";
import { ApolloServer } from "apollo-server-express";
import { context } from "./lib/context";
import { pubsub } from "./lib/context";
import { PassportGoogle } from "./lib/passport/config";
import { GoogleAuthenticate } from "./lib/passport/socialMediaAuth";
import express from "express";
import passport from "passport";
import cookieParser from "cookie-parser";
import cors from "cors";
import * as AllTypes from "./services/index";
PassportGoogle();
(async function () {
const app = express();
const httpServer = createServer(app);
const schema = makeExecutableSchema({
typeDefs,
resolvers: {
...AllResolvers,
...AllTypes,
},
});
const corsOptions = {
origin: true,
credentials: true,
};
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.set("trust proxy", 1);
app.use(cors(corsOptions));
app.use(cookieParser());
// Google login auth
app.get(
"/auth/google",
passport.authenticate("google", { scope: ["profile", "email"] })
);
// Google callback
app.get(
process.env.GOOGLE_CALLBACK_ROUTE!,
passport.authenticate("google", {
session: false,
failureRedirect: `${process.env.FRONTEND_URI}/auth/signin`,
}),
GoogleAuthenticate
);
const subscriptionServer = SubscriptionServer.create(
{
schema,
execute,
subscribe,
async onConnect() {
return { pubsub };
},
},
{ server: httpServer, path: "/graphql" }
);
const server = new ApolloServer({
schema,
plugins: [
{
async serverWillStart() {
return {
async drainServer() {
subscriptionServer.close();
},
};
},
},
ApolloServerPluginLandingPageGraphQLPlayground(),
],
context,
introspection: true,
});
await server.start();
server.applyMiddleware({ app, cors: corsOptions });
const PORT = process.env.PORT || 4000;
httpServer.listen(PORT, () =>
console.log(
`🚀 Server and WS is now running on http://localhost:${PORT}/graphql or ws://localhost:${PORT}/graphql ${process.env.FRONTEND_URI}`
)
);
})(); My token handler // Token Handler
import JWT from "jsonwebtoken";
import { Response } from "express";
const JWT_SECRET = process.env.JWT_SECRET || "secret";
export const createToken = (userId: string, username: string) =>
JWT.sign({ userId, username }, JWT_SECRET, { expiresIn: "1d" });
export const sendToken = (res: Response, token: string) =>
res.cookie(process.env.COOKIE_NAME!, token, {
secure: process.env.NODE_ENV === "development" ? false : true,
httpOnly: true,
});
export const verifyToken = (token: string) => {
try {
return JWT.verify(token, JWT_SECRET) as {
userId: string;
username: string;
iat: number;
exp: number;
} | null;
} catch (error) {
return null;
}
}; my contex import { AppContext, Context } from "@interface/context";
import { prisma } from "../lib/prisma";
import { PubSub } from "graphql-subscriptions";
import { verifyToken, createToken, sendToken } from "../utility/tokenHandlers";
export const db = prisma;
export const pubsub = new PubSub();
export const context = async ({ res, req }: AppContext): Promise<Context> => {
// get token from cookie
const token = req.cookies[`${process.env.COOKIE_NAME!}`];
if (token) {
// Verify token
const decoded = verifyToken(token);
// if was decoded
if (decoded) {
req.userId = decoded.userId;
req.username = decoded.username;
// Re generate token if below conditions are met
if (Date.now() / 1000 - decoded.iat > 6 * 60 * 60) {
// find it in prisma db
const findUser = await db.user.findUnique({
where: {
id: req.userId,
},
});
if (findUser) {
const newToken = createToken(findUser.id, findUser.username);
// send it
sendToken(res, newToken);
}
}
}
}
return {
db,
res,
req,
pubsub,
};
}; Please help me... Any suggestion and answer i will appreciate <3 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
Just to confirm, is your Heroku server using |
Beta Was this translation helpful? Give feedback.
Just to confirm, is your Heroku server using
https
and what's theNODE_ENV
deployed with? That seems like the likely culprit here since it's the only conditional behavior you have.