1
votes

So I have an Express / TypeGraphql backend running at localhost:5000 and Next / React app running at localhost:3000. I decided to use apollo-server for graphql API and apollo-client for the front end. After a successful login, I store httpOnly cookies in web browser.

What I want to do is, get cookies in every request and authorize the user if oauth2 tokens are valid. Even though requests are valid, and I get the query, cookies are shown as null. Also, I got no error in the console.

Here I save cookies =>

server.tsĀ 

app.get('/auth/google/callback', function (req, res, next) {
    passport.authenticate('google', { session: false }, (err, user, info) => {
        if (err) return next(err);
        if (!user) return res.redirect('/');
        res.cookie('login_cookie', JSON.stringify(info), {
            secure: false,
            httpOnly: true,
            expires: dayjs().add(30, 'days').toDate(),
            sameSite: false,
        });
        return res.redirect('http://localhost:3000/home');
    })(req, res, next);
});

Here I log cookies to console after a request =>

resolver.ts

@Query(() => [User])
async users(@Ctx() ctx: Context) {
    console.log('cookies ', ctx.req.cookies);
    return await ctx.prisma.user.findMany();
}

and lastly, this is my apollo client config =>

apollo-client.ts

const client = new ApolloClient({
  cache: new InMemoryCache(),
  credentials: "include",
  uri: "http://localhost:5000/graphql",
});

After every request my console shows cookies: [Object: null prototype] {} even though I see them in browser's cookie storage.

request.ts

export async function getServerSideProps() {
const { data } = await client.query({
  query: gql`
    query allUsers {
      users {
        id
        username
      }
    }
  `,
});

return {
  props: {
    users: data.users,
  },
};

}

1
Do you make GraphQL requests in the backend e.g. to server side render certain views? I think you would have to forward the cookies to your GraphQL backend. Maybe github.com/valeriangalliat/fetch-cookie could help? - Herku
I edited the question. I make my request like that, also it should automatically send the cookies in every request that I make to the backend. I don't think I need a package to do that. - altF4

1 Answers

3
votes

I think you have not fully understood Next.js yet. Next.js renders views on the server or alternatively sends "server side props" to the client. This means getServerSideProps gets executed on the server (as the name suggests). Cookies are a feature of the browser. So what happens?

  1. Browser sends request to Next.js. If your Next.js server and your GraphQL server are on the same domain, the request includes the Cookie header.
  2. Next.js receives request and executes getServeSideProps.
  3. Next.js Apollo Client makes request to server, missing the cookies, because the cookies are only in the browser's initial request!

This means you would have to first make sure that your Next.js server receives the cookies from the frontend. This should happen automatically, if it is on the same origin as the GraphQL server. Otherwise it is a bit tricky and it should be easier to work with an explicit Authorization header in this case. Then you have to pass on the cookies with the request. This can be done by accessing req in getServerSiteProps and using the context in client.query.

export async function getServerSideProps(context) {
  const Cookie = context.req.headers.Cookie;
  const { data } = await client.query({
    context: { headers: { Cookie } },
    query: gql`
      query allUsers {
        users {
          id
          username
        }
      }
    `,
  });

  return {
    props: {
      users: data.users,
    },
  };
}

Code is untested, but I think you get the idea.