apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.

Home Page:https://apollographql.com/client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Apollo Client does not pass cookies

serendipity1004 opened this issue · comments

I am currently using nextJS with apollo and it's completely unusable for me because the cookie is not passing in every request.

I would be much grateful if someone can just point me to right direction to pass cookies properly.

Even the apollo nextjs example is buggy itself https://github.com/adamsoffer/next-apollo-example

Even in that example, cookies are not being sent in the request.

I am trying every possible way of setting cookies in config without success.

Some people say swapping ApolloClient to ApolloBoost have solved it but neither of the packages work for me.

Below is an example of what I have tried

new ApolloClient({
        connectToDevTools: process.browser,
        ssrMode: !process.browser, // Disables forceFetch on the server (so queries are only run once)
        link: new HttpLink({
            uri: APOLLO_ENDPOINT, // Server URL (must be absolute)
            opts:{
                credentials:'include'
            },
            credentials: 'include', // Additional fetch() options like `credentials` or `headers`,
        }),
        cache: new InMemoryCache().restore(initialState || {}),
        fetchOptions:{
            credentials:'include'
        },
        credentials:'include'
    })

I am using following dependencies

    "apollo-boost": "^0.1.22",
    "apollo-client": "^2.4.7",
    "apollo-link-context": "^1.0.10",
    "apollo-link-http": "^1.5.7",

I have the same issue with apolloboost the cookies not sent with the request

Same here

Same here, anyone have any luck with this?

I think you need to verify your server the issue for me was the cors i was passing cors options in the wrong place now it works as expected

@serendipity1004 works here. Doesn't it work during SSR or on client side?

Figured it out. credentials:'include' should be in the root of the config. Like,

new ApolloClient({
  credentials: 'include',
})

I was using inside of fetchOptions...

I'm pretty sure I'm still having this issue. My rest calls have cookies attached, however my graphql queries don't.

I'm having a similar problem, but I actually think it is a browser issue and nothing to do with the Apollo Client.

When I have my front-end hosted on Heroku like frontend.herokuapp.com and my yoga backend on something like backend.herokupapp.com, my Graphql queries will only retain the cookie if my browsers do NOT have "Disable 3rd Party Cookies" set or Safari's "Prevent Cross-site Tracking" enable.

It seems to me, the browser considers any cookie from different subdomain's to be 3rd party.

There are varying degrees of this:

Opera - Cookies blocked if "Block Third Party Cookies" enabled
Firefox - Cookies work even with Block Third Party Cookies - Trackers" enabled but blocked if "All third party cookies" is selected
Chrome - Cookies work unless "Block Third Party Cookies" enabled

Hi, I found that when I want to make request with "Cookie" then apollo client is not sending it, but just when I change it to "Cookies" then everything is ok XD

Hi there,

I'm still having the issue here. I'm working with:

  • Angular 7
  • Apollo-client 2.4.7
  • Chrome with cookie enabled and no extension

withCredentials is sets to true in my apollo.config.ts file:

    const uri = '/graphql';
    const link = httpLink.create({
      uri,
      withCredentials: true
    });

    apollo.create({
      link,
      cache: new InMemoryCache(),
      defaultOptions: {
        watchQuery: {
          errorPolicy: 'all'
        }
      },
      connectToDevTools: true
    });

Is there anybody that can tell us why ?

Hi, I found that when I want to make request with "Cookie" then apollo client is not sending it, but just when I change it to "Cookies" then everything is ok XD

@rrakso Did you mean like this?

headers: { cookies: ... }

Anyone have any further insight?

@rrakso Could you provide a snippet of what is working for you?

i'm using next-with-apollo and it's working, you can do something like this

// createClient.js
import ApolloClient from "apollo-boost";
import withData from "next-with-apollo";

const createClient = ({ headers }) => {
  return new ApolloClient({
    uri: process.env.ENDPOINT,
    request: operation => {
      operation.setContext({
        fetchOptions: {
          credentials: "include"
        },
        headers
      });
    }
  });
};

export default withData(createClient);
// index.js server
const cookieParser = require("cookie-parser");
require("dotenv").config({ path: "var.env" });
const createServer = require("./createServer");

const server = createServer();

server.express.use(cookieParser());

server.express.use((req, res, next) => {
  const { token } = req.cookies;
  console.log(token);
  next();
});

server.start(
  {
    cors: {
      credentials: true,
      origin: ["http://localhost:3000"] // frontend url.
    }
  },
  r => console.log(`Server is running on http://localhost:${r.port}`)
);

Figured it out. credentials:'include' should be in the root of the config. Like,

new ApolloClient({
  credentials: 'include',
})

I was using inside of fetchOptions...

This also fixed my issue, the docs are a bit confusing as credentials: 'include' is nested under fetchOptions; putting in the root fixed my issue. Is there a reason why this option can be put in two places? Only the root worked for me and caused a lot of confusion

commented

FYI: I'm using fetch, and axios, thats what's not setting the cookie header for me.

I had to do this for our build a few days ago, here is how I did it - https://gist.github.com/neil-gebbie-smarterley/cd8356df4c786c4c9dacfc9d46e890ac

Our set it is:
Next/Apollo Client/Apollo Server/REST data source

It's basically just passing it through to the server, I'm not sure if the document.cookie is needed for subsequent requests, but it seems to be working ok for us, not in production yet, but it's passing cookies.

Oddly enough, what worked for me was to set an AuthLink with setContext from apollo-link-context and call localStorage.getItem("") within it like so:

const authLink = setContext((_, { headers }) => {
  const token = localStorage.getItem("");

  return {
    headers: {
      ...headers,
    }
  };
});

I'm not sure if this is a good workaround (maybe dangerous?); you'll be bombarded with reference errors as localStorage is not available when NextJS renders in server-side.

Edit: Eh...doesn't work on mobile.

This works for me:

  return new ApolloClient({
    uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
    request: operation => {
      operation.setContext({
        fetchOptions: {
          credentials: 'include',
        },
        headers: { cookie: headers && headers.cookie },
      });
    },
    .......
  });

Put the credentials: "include" in your httpLink, like so.

const httpLink = createHttpLink({ uri,  credentials: 'include',
 });

Then put that in your ApolloClient. Worked finally without a bunch of custom stuff.

commented

I've fixed it for myself using the latest libraries next@9.0.3, next-with-apollo@4.2.0 and react-apollo@3.0.0. Cookies are passed with every request, SSR working as expected and no errors. Code is here. I had to remove .restore(initialState || {}) so it's just cache: new InMemoryCache() and now it's fully working. Only thing still not working is Safari. Anyone fixed it for Safari?

I'm pretty sure I'm still having this issue. My rest calls have cookies attached, however my graphql queries don't.

@RiChrisMurphy I'm seeing a similar issue. Were you able to find a fix for that?

@helfi92 Have you tried any of the solutions in this thread?

I think I understand what's happening. The client and server I'm working with are both subdomains of herokuapp (e.g.., ui.herokuapp.com and web-server.herokuapp.com). From https://devcenter.heroku.com/articles/cookies-and-herokuapp-com:

applications in the herokuapp.com domain are prevented from setting cookies for *.herokuapp.com

Using a custom domain will probably resolve the issue.

I've been trying in Razzle to no avail. Cookies are passed to playground very ok, but on razzle it's not

@juicycleff What does your createApolloClient file look like?

Do you have a withApolloClient HOC?

I'm still having an issue where the cookies are not getting sent at all, even with all of the above suggestions.

@seawatts are you using Apollo client and Apollo server?

Yeah I have tried the following

import { ApolloClient } from 'apollo-client';

const client = new ApolloClient({
    link: ApolloLink.from([
      new HttpLink({
        headers,
        fetchOptions: {
          credentials: 'include',
        },
        uri: process.env.REACT_APP_SERVER_URL,
        credentials: 'include',
      }),
    ]),
    cache: new InMemoryCache(),
  });

and

import ApolloBoostClient from 'apollo-boost';

const client = new ApolloClient({
  uri: process.env.REACT_APP_SERVER_URL,
  headers,
  credentials: 'include',
  fetchOptions: {
    credentials: 'include',
  },
});

Then on the server side I'm using graphql-yoga

I think you need to explicitly pass the cookies through getInitialProps in your withApolloClient HOC. Check out the gist(https://gist.github.com/neil-gebbie-smarterley/cd8356df4c786c4c9dacfc9d46e890ac) I posted - it might look like a lot of work to get it going, but if you log the cookies out at every step of the process you can see them being passed along from the browser through Apollo, and then onto it's final destination.

We have this set up working in production.

I had this issue using apollo client and apollo-server-express

With my use-case I needed to put credentials: 'include' in two places:

First, the cookie was not being created. Adding credentials: 'include' to createHTTPLink() solved this. Then I was getting connection refused errors when I would query the server. Placing credentials: 'include' in new ApolloClient() solved this issue.

commented

@mdashmiller thanks. It worked for me as well. 😃

const httpLink = createUploadLink({
  uri: util.graphQLUrl(),
  credentials: 'include',
});
export default new ApolloClient({
  link,
  cache: new InMemoryCache(),
  credentials: 'include',
});

After doing this, the session created on back-end via express-session now appears in Application > Cookies 😍

It seems that mixing headers: {...} and credentials: 'include' overrides the entire header and removes all cookie related content:

export default new ApolloClient({
  link,
  cache: new InMemoryCache(),
  headers: {
    'x-custom-header': 'test'
   },
  credentials: 'include',
});

In this case I would expect the headers to contain the cookies and the x-custom-header header. It now only includes the x-custom-header.

I've observed the same behavior described by @dkln
Cookies are not included when both headers and credentials are used

For me what worked was just to set the credentials option also in the POST request for the login endpoint. If you're are using axios like this

    axios
    .post(loginEndpoint, loginParams, { withCredentials: true }) // set withCredentials to true is important!
    .then(response => {
      // handle response
    })

or fetch

response = await fetch (loginEndpoint, {
    method: 'POST',
    credentials: 'include', // set credentials to 'include' is important!
    body: JSON.stringify({
        email,
        pw
    })
})
json = await response.json();

Just for completeness this is my ApolloClient setup:

const createApolloClient = () => {
  return new ApolloClient({
    link: new HttpLink({ uri: EXAMPLE_URL, credentials: 'include' }),
    cache: new InMemoryCache(),
  })
}

Hope this helps someone else too

commented

Guys, do not mess with headers!!! It will overwrite session! Still don't know how to set custom headers and not lose session, anyone thoughts?

For anyone struggling with cookies being wiped out on refresh, initial load after deploying to production. You have to attach a domain option to your mutation in res.cookie like:
{ domain: '.yourdomain.com' }
Then will the cookies work on refresh if your frontend is at frontend.yourdomain.com and backend at backend.yourdomain.com. It worked on localhost without this additional setting, because it's the same domain for backend and frontend: localhost. I lost a month on this only thinking it was Apollo Client issue.

As both @lawwantsin and @chemicalkosek stated, to ensure that my cookie is boh not wiped out and detected on refresh, I did the following:

  1. ApolloClient
  const httpLink = createHttpLink({
    uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
    credentials: 'include',
  });
  1. Back end
      const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
      ctx.res.cookie('token', token, {
        domain: process.env.NODE_ENV === 'development' ? process.env.LOCAL_DOMAIN : process.env.APP_DOMAIN,
        secure: process.env.NODE_ENV === 'development' ? false : true,
        httpOnly: true,
        maxAge: 1000 * 60 * 60 * 24 * 365, // 1 year cookie
        sameSite: 'lax',
      });

FWIW my issue was that i did not set with credentials to 'true' in my login call (using axios) - which resulted in subsequent Apollo calls not sending the cookie. So not an issue with Apollo.

Took us a while to figure this out, but here were our couple of sticking points.

Currently the only place we configured credentials: 'include' was in the HttpLink configuration object. This will fail giving you a cors error if you have not already set them up.

Assuming your setup is similar to ours, you are using the applyMiddleware function to make changes to an instance of an express server. Within this object is where you must pass your cors configuration.

Ours looks like this for example (for dev):

{
  origin: 'http://localhost:3000',
  optionsSuccessStatus: 200,
  credentials: true,
};

All of a sudden our client was passing cookies. Good luck!

omg I spent so long on this.

Here is how my setup looks:

  1. Auth Server - Keycloak - auth.domain.com
  2. SSR Sapper/Svelte App - www.domain.com
  3. graphql api - content.domain.com

For me, credentials: true on the server (localhost:3001), and credentials: 'include' on the client got things working for me on localhost!

... Then I deployed...

Once I deployed with SSL and the works to Kubernetes, cors was working, but cookies were not being shared.

I must have tried 800 combinations before I came across the concept of a domain cookie.

Should that cookie be the FQDN? The Auth server? The API Server?

I use passport on www which is where the user logs in, and the cookie is stored. I assumed this meant I should use that www FQDN (https://www.domain.com). This did not work.

Turns out you can use cookies across subdomains (not domains), however, and this DID finally work. To do so, set the domain value to .domain.com the cookies started getting passed around!

From the www server:

const cookieSettings = {
  maxAge: 24 * 60 * 60 * 1000,
  keys: config.sessionKey,
  secure: !dev
}

if (!dev && config.cookie && config.cookie.domain) {
  cookieSettings.domain = config.cookie.domain // value: ".domain.com"
}

Hey, I have the same issue and I can't resolve it
My FR (Vercel) & BE (Heroku) both are on a subdomains

On Firefox Set-Cookie is not coming from response on Chrome/Brave Set-Cookie is coming but after page reload redirects me to the login page.

This example is working on localhost but not after deploying it.

Apollo client

import withApollo from 'next-with-apollo'
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import fetch from 'isomorphic-unfetch'

export default withApollo(({ initialState, headers }) => {
  const isBrowser = typeof window !== 'undefined'
  const backendUrl = ...
  return new ApolloClient({
    connectToDevTools: isBrowser,
    ssrMode: !isBrowser,
    link: createHttpLink({
      uri: `${backendUrl}/graphql`,
      credentials: 'include',
      ...(!isBrowser && { fetch }),
      headers: {
        ...headers,
        cookie: headers?.cookie,
      },
    }),
    cache: new InMemoryCache().restore(initialState || {}),
  })
})

My Next.js _app.js

const MyApp = ({ Component, pageProps, apollo }) => (
  <>
        <ApolloProvider client={apollo}>
          <UserProvider>
            <SEO />
            <Header />
            <main role="main">
              <Component {...pageProps} />
            </main>
          </UserProvider>
        </ApolloProvider>
  </>
)

MyApp.getInitialProps = async ({ Component, ctx }) => {
  let pageProps = {}

  const { loggedInUser } = await checkLoggedIn(ctx.apolloClient)

  // Check whether path is an "authorization" specific page
  const auth = isAuthPath(ctx.asPath)

  if (!loggedInUser.me) {
    // User is not logged in. Redirect to Login.
    if (!auth) redirect(ctx, '/login')
  } else if (auth) {
    // User is logged in. Redirect to Dashboard.
    redirect(ctx, '/')
  }

  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx)
  }

  return { pageProps, loggedInUser }
}

export default withApollo(MyApp)
 "@apollo/react-hooks": "^3.1.5",
 "apollo-cache-inmemory": "^1.6.6",
 "apollo-client": "^2.6.9",
 "apollo-link-http": "^1.5.17",
 "graphql": "^15.0.0",
 "graphql-tag": "^2.10.3",
 "isomorphic-unfetch": "^3.0.0",
 "next": "9.4.0",
 "next-with-apollo": "^5.0.1",
 "react": "16.13.1",
 "react-dom": "16.13.1",

Server code:

app.set('trust proxy', 1)

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

app.use(
  cors({
    origin: process.env.FRONTEND_URL || `http://localhost:3000`,
    credentials: true,
  }),
)

app.use(
  session({
    store,
    name: process.env.SESS_NAME,
    secret: process.env.SESS_SECRET,
    saveUninitialized: false,
    resave: false,
    cookie: {
      secure: !dev,
      httpOnly: true,
      domain: process.env.SESS_DOMAIN,
      maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days
    },
  }),
)

@byurhanbeyzat

My FR (Vercel) & BE (Heroku) both are on a subdomains

You should have frontend and backend on subdomains within the same domain.
Like frontend.yourdomain.com and backend.yourdomain.com.
Then the cookies will be set.

Also I don't think you should spread headers there. At least it was breaking my code.

@chemicalkosek

My FR (Vercel) & BE (Heroku) both are on a subdomains

You should have frontend and backend on subdomains within the same domain.
Like frontend.yourdomain.com and backend.yourdomain.com.
Then the cookies will be set.

Also I don't think you should spread headers there. At least it was breaking my code.

Yes, they both are on same custom domain. If I remove headers it's not working event on localhost.

What is your process.env.SESS_DOMAIN
It should be yourdomain.com.

@chemicalkosek
SESS_DOMAIN - '.bbn.codes'
app - bank.bbn.codes
api - bank-api.bbn.codes

@byurhanbeyzat It looks like the cookie is not being wiped out on refresh, hmmm.
Well I don't know :( . Btw you're using next-with-apollo 5.0.0, you should pass getDataFromTree in order to have SSR

// import { getDataFromTree } from '@apollo/react-ssr';
// You can also override the configs for withApollo here, so if you want
// this page to have SSR (and to be a lambda) for SEO purposes and remove
// the loading state, uncomment the import at the beginning and this:
//
// export default withApollo(Index, { getDataFromTree });

console.log your cors and cookie settings to make sure they actually are what you expect

Thank you everyone. I found solution for myself
I've decided to use next-apollo-example that I found on the internet with a little tweaks.

If someone needs here is the code

initApollo.js

import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { createHttpLink } from 'apollo-link-http'
import { setContext } from 'apollo-link-context'
import fetch from 'isomorphic-unfetch'

let apolloClient = null

// Polyfill fetch() on the server (used by apollo-client)
if (typeof window === 'undefined') {
  global.fetch = fetch
}

function create(initialState, { getToken, fetchOptions }) {
  const backendUrl =
    process.env.NODE_ENV === 'production'
      ? `https://bank-api.bbn.codes`
      : 'http://localhost:2000'

  const httpLink = createHttpLink({
    uri: `${backendUrl}/graphql`,
    credentials: 'include',
    fetchOptions,
  })

  const authLink = setContext((_, { headers }) => {
    const token = getToken()

    return {
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : '',
      },
    }
  })

  // Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
  const isBrowser = typeof window !== 'undefined'

  return new ApolloClient({
    connectToDevTools: isBrowser,
    ssrMode: !isBrowser, // Disables forceFetch on the server (so queries are only run once)
    link: authLink.concat(httpLink),
    cache: new InMemoryCache().restore(initialState || {}),
  })
}

export default function initApollo(initialState, options) {
  // Make sure to create a new client for every server-side request so that data
  // isn't shared between connections (which would be bad)
  if (typeof window === 'undefined') {
    let fetchOptions = {}

    // If you are using a https_proxy, add fetchOptions with 'https-proxy-agent' agent instance
    // 'https-proxy-agent' is required here because it's a sever-side only module
    if (process.env.https_proxy) {
      fetchOptions = {
        // agent: new (require('https-proxy-agent'))(process.env.https_proxy),
      }
    }

    return create(initialState, {
      ...options,
      fetchOptions,
    })
  }

  // Reuse client on the client-side
  if (!apolloClient) {
    apolloClient = create(initialState, options)
  }

  return apolloClient
}

witApollo.js

import React from 'react'
import cookie from 'cookie'
import Head from 'next/head'
import PropTypes from 'prop-types'
import { getDataFromTree } from '@apollo/react-ssr'

import initApollo from './initApollo'

function parseCookies(req, options = {}) {
  return cookie.parse(req ? req.headers.cookie || '' : document.cookie, options)
}

export default (App) => {
  return class WithData extends React.Component {
    static displayName = `WithData(${App.displayName})`

    static propTypes = {
      apolloState: PropTypes.object.isRequired,
    }

    static async getInitialProps(ctx) {
      const {
        Component,
        router,
        ctx: { req, res },
      } = ctx
      const apollo = initApollo(
        {},
        {
          getToken: () => parseCookies(req).sessionId,
        },
      )
      ctx.ctx.apolloClient = apollo
      let appProps = {}

      if (App.getInitialProps) {
        appProps = await App.getInitialProps(ctx)
      }

      if (res && res.finished) {
        // When redirecting, the response is finished.
        // No point in continuing to render
        return {}
      }

      if (typeof window === 'undefined') {
        // Run all graphql queries in the component tree
        // and extract the resulting data
        try {
          // Run all GraphQL queries
          await getDataFromTree(
            <App
              {...appProps}
              Component={Component}
              router={router}
              apolloClient={apollo}
            />,
          )
        } catch (error) {
          // Prevent Apollo Client GraphQL errors from crashing SSR.
          // Handle them in components via the data.error prop:
          // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
          console.error('Error while running `getDataFromTree`', error)
        }
        // getDataFromTree does not call componentWillUnmount
        // head side effect therefore need to be cleared manually
        Head.rewind()
      }

      // Extract query data from the Apollo's store
      const apolloState = apollo.cache.extract()
      return {
        ...appProps,
        apolloState,
      }
    }

    constructor(props) {
      super(props)
      // `getDataFromTree` renders the component first, the client is passed off as a property.
      // After that rendering is done using Next's normal rendering pipeline
      this.apolloClient = initApollo(props.apolloState, {
        getToken: () => {
          return parseCookies().sessionId
        },
      })
    }

    render() {
      return <App {...this.props} apolloClient={this.apolloClient} />
    }
  }
}

_app.js

const MyApp = ({ Component, pageProps, apolloClient }) => (
  <>
  	<ApolloProvider client={apolloClient}>
        <SEO />
       	<Header />
        	<main role="main">
        	<Component {...pageProps} />
    	</main>
  	</ApolloProvider>
  </>
)

MyApp.getInitialProps = async ({ Component, ctx }) => {
  let pageProps = {}

  const { loggedInUser } = await checkLoggedIn(ctx.apolloClient)

  // Check whether path is an "authorization" specific page
  const auth = isAuthPath(ctx.asPath)

  if (!loggedInUser.me) {
    // User is not logged in. Redirect to Login.
    if (!auth) redirect(ctx, '/login')
  } else if (auth) {
    // User is logged in. Redirect to Dashboard.
    redirect(ctx, '/')
  }

  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx)
  }

  return { pageProps, loggedInUser }
}

export default withApollo(MyApp)

And added this middleware code to the backend

app.use((req, _, next) => {
  const { authorization } = req.headers

  if (authorization) {
    const token = authorization.split(' ')[1]
    req.headers.cookie = `${process.env.SESS_NAME}=${token}`
  }

  return next()
})
commented

I am also struggling with this and have been for weeks, Im at a total loss as to what to do/what is causing this. Similarly to the above, I am also getting the issue where refreshing causes the cookie to be deleted/destroyed.
I only notice this behaviour on production where I am running my server on a subdomain.(api.mydomain.xyz), Locally on localhost it all works fine - my guess this is down to the subdomain. If I change my createHttpLink uri to 127.0.0.1 the app works but I get the same behaviour as in prod, the cookie is deleted on refresh. Again, my guess is that this is down to it being a different domain/subdomain?
I have tried to cut out irrelevant code, so apologies for dumping code but I dont know what else to do at this stage:

FRONTEND
apollo.js

function parseCookies(req, options = {}) {
  return cookie.parse(req ? req.headers.cookie || '' : document.cookie, options)
}
let globalApolloClient = null

export const initOnContext = (ctx) => {
  const inAppContext = Boolean(ctx.ctx)

  if (process.env.NODE_ENV === 'development') {
    if (inAppContext) {
      console.warn(
        'Warning: You have opted-out of Automatic Static Optimization due to `withApollo` in `pages/_app`.\n' +
          'Read more: https://err.sh/next.js/opt-out-auto-static-optimization\n'
      )
    }
  }
  const apolloClient =
    ctx.apolloClient || initApolloClient(ctx.apolloState || {}, inAppContext ? ctx.ctx : ctx, ctx.req || {})
  apolloClient.toJSON = () => null

  ctx.apolloClient = apolloClient
  if (inAppContext) {
    ctx.ctx.apolloClient = apolloClient
  }

  return ctx
}

const initApolloClient = (initialState, ctx) => {
  const { req } = ctx || {}

  if (typeof window === 'undefined') {
    return createApolloClient(initialState, ctx, {
      getToken: () => parseCookies(req).qid
    })
  }

  if (!globalApolloClient) {
    globalApolloClient = createApolloClient(initialState, ctx, {
      getToken: () => parseCookies().token
    })
  }

  return globalApolloClient
}

export const withApollo = ({ ssr = false } = {}) => (PageComponent) => {
  const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
    let client
    if (apolloClient) {
      client = apolloClient
    } else {
      client = initApolloClient(apolloState, undefined)
    }

    return (
      <ApolloProvider client={client}>
        <PageComponent {...pageProps} />
      </ApolloProvider>
    )
  }
  if (process.env.NODE_ENV !== 'production') {
    const displayName = PageComponent.displayName || PageComponent.name || 'Component'
    WithApollo.displayName = `withApollo(${displayName})`
  }

  if (ssr || PageComponent.getInitialProps) {
    WithApollo.getInitialProps = async (ctx) => {
      const inAppContext = Boolean(ctx.ctx)
      const { apolloClient } = initOnContext(ctx)

      // Run wrapped getInitialProps methods
      let pageProps = {}
      if (PageComponent.getInitialProps) {
        pageProps = await PageComponent.getInitialProps(ctx)
      } else if (inAppContext) {
        pageProps = await App.getInitialProps(ctx)
      }
      if (typeof window === 'undefined') {
        const { AppTree } = ctx
        if (ctx.res && ctx.res.finished) {
          return pageProps
        }

        if (ssr && AppTree) {
          try {
            const { getDataFromTree } = await import('@apollo/react-ssr')
            let props
            if (inAppContext) {
              props = { ...pageProps, apolloClient }
            } else {
              props = { pageProps: { ...pageProps, apolloClient } }
            }

            await getDataFromTree(<AppTree {...props} />)
          } catch (error) {
            if (error.message.includes('Not Logged In')) redirect(ctx, '/login')
          }
          Head.rewind()
        }
      }

      return {
        ...pageProps,
        apolloState: apolloClient.cache.extract(),
        apolloClient: ctx.apolloClient
      }
    }
  }

  return WithApollo
}

apolloClient.js

export default function createApolloClient(initialState, ctx, { getToken }) {
  const httpLink = createHttpLink({
    uri: process.env.NODE_ENV === 'production' ? 'https://api.mydomain.xyz/' : 'http://localhost:4000',
    credentials: 'include',
    fetch
  })
  const authLink = setContext((_, { headers }) => {
    const token = getToken()
    return {
      headers: {
        ...headers,
        cookie: token ? `qid=${token}` : ''
      }
    }
  })
  const errorLink = onError(({ graphQLErrors, networkError }) => {
    if (graphQLErrors)
      graphQLErrors.forEach(({ message, locations, path }) => {
        if (message.includes('Not Logged In')) redirect(ctx, '/signup')
      })
    if (networkError) console.log(`[Network error]: ${networkError}`)
  })
  return new ApolloClient({
    ssrMode: Boolean(ctx),
    link: errorLink.concat(authLink.concat(httpLink)),
    cache: new InMemoryCache().restore(initialState),
    credentials: 'include'
  })
}

BACKEND
index.ts

const main = async () => {
  await createConnection(DB_CONFIG)
    .then(() => console.log('🚀 Connected to Database'))
    .catch((err) => {
      console.log('❌ Error connecting to Database:');
      console.log(err);
    });

  const schema = await buildSchema({
    resolvers: [all my resolvers here]
  });
  const apolloServer = new ApolloServer({
    schema,
    context: ({ req, res }) => ({ req, res })
  });

  const app = Express();
  app.use(Helmet());

  app.use(
    cors({
      credentials: true, // Enables HTTP cookies over CORS
      origin: process.env.NODE_ENV === 'production' ? 'https://mydomain.xyz' : 'http://localhost:3000'
    })
  );

  const RedisStore = connectRedis(session);

  process.env.NODE_ENV === 'production' && app.set('trust proxy', true);

  const sessionOption: session.SessionOptions = {
    store: new RedisStore({
      client: redis
    }),
    name: 'qid',
    secret: '1234567890',
    resave: false,
    proxy: process.env.NODE_ENV === 'production',
    saveUninitialized: false,
    cookie: {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      maxAge: 1000 * 60 * 60 * 24 * 365 // 1 year cookie
    }
  };

  app.use(session(sessionOption));

  apolloServer.applyMiddleware({ app, path: '/', cors: false });

  app.listen(4000, () => console.log('🚀 Server ready'));
};

main();

Just to note also, I have tried setting a domain value in the cookie object in the above backend index.ts file, which didnt fix/change anything

@alex-r89 I think you should also apply the same cors options to .applyMiddleware. You can try also cors settings in app.listen. At least that's how it's working for me

const corsOptions = {
  origin: process.env.FRONTEND_URL,
  credentials: true,
};

server.applyMiddleware({ app, cors: corsOptions, path: '/' });
app.listen(
  {
    port: process.env.PORT || 4000,
    cors: corsOptions,
    path: '/',
  },
  () => console.log(`Server is running at ${server.graphqlPath}`)
);

You should also try to set the domain value in the cookie object because it might be set with your server domain api.mydomain.xyz and not .mydomain.xyz (check in devtools with what domain the cookie is created, I'm not sure right now)

commented

Hi @chemicalkosek thanks for the reply. I have tried that, unfortunately it made no difference.

I have also tried with the domain value on the cookie, again to no avail. It seems odd that the cookie works on the root domain but not on a subdomain.

One thing I have noted is that the domain value of the cookie in dev tools reflects whatever value I put in the uri of my createHttpLink. For example, if I put this as 127.0.0.1 my cookie domain will be as so and the site will work perfectly on http://127.0.0.1. The same for localhost. However visiting http://localhost:3000 while this uri value is 127.0.0.1 causes the cookie to be stored and then deleted on refresh. Im not too sure what this means though?

I struggled with this for a while, the request would always be missing Cookies no matter where I put credentials: 'include'. The issue ended up being the "content-type": "application/json" header. If I removed that the request worked fine. I found it helpful to use the fetch argument to debug this:

const customFetch = (uri, options) => {
  return fetch(
    `${ENDPOINT}/graphql/query`,
    {
      // Uncomment to have credentials break
      // headers: options.headers,
      method: 'POST',
      credentials: 'include',
      body: options.body,
    },
  );
};

export const client = new ApolloClient({
  link: createHttpLink({
    fetch: customFetch,
  }),
  cache: new InMemoryCache(),
});

Thanks @counterbeing!

Took us a while to figure this out, but here were our couple of sticking points.

Currently the only place we configured credentials: 'include' was in the HttpLink configuration object. This will fail giving you a cors error if you have not already set them up.

Assuming your setup is similar to ours, you are using the applyMiddleware function to make changes to an instance of an express server. Within this object is where you must pass your cors configuration.

Ours looks like this for example (for dev):

{
  origin: 'http://localhost:3000',
  optionsSuccessStatus: 200,
  credentials: true,
};

All of a sudden our client was passing cookies. Good luck!

This worked for me. Added credentials: true on the Apollo client creation, and also added

{
  ...
  optionsSuccessStatus: 200,
  credentials: true,
}

on the GraphQL server cors config, and now it's working.

Anybody get this working with NextJS?

Thanks @neil-gebbie-smarterley it pointed me in the right direction

This one worked for me as a proof of concept with Apollo NextJS and Cookies from @mzygmunt https://gist.github.com/lionelyoung/6f9020de23f257599bdabfdb0bf40bff and I will adjust it more toward neil's solution

Hi there,
Thanks for your precious infos.

We want to store refreshTokens only (not authToken) in an httpOnly cookie but if we use credentials:include, the refresh token will be passed on every request which is far from optimal.
Is my use case unique or am I missing something?

Thanks

@cyril94440 - How often to you anticipate to make requests? do you not need the auth token to make the requests?

This is a good article that will be able to help you alot more then I could - https://auth0.com/docs/tokens/token-storage

@neil-gebbie-smarterley - I have an authToken saved in memory that expires every 10mn that I pass on each and every requests. And a long-lived refreshToken that I must NOT pass on every requests saved in an httpOnly cookie. This refresh token is used every 10mn to get a new authToken and a new refreshToken.

Thanks I'll take a look at it.

I'm also having issues setting cookies. I'm using Ember Apollo Client.

We use the following link:

testAuthMiddleware = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      authorization: this.currentUser,
      cookie: "CurrentDistrictCode=12345"
    },
  });

  return forward(operation);
});

Then I add it to the list of Apollo Links.

I was able to successfuly send headers but not cookies. Like if I add a header called "CurrentDistrictCode", I saw that in the headers. But when I use the cookie key like above, I don't see it in the cookies.

I've had same issue but it seemed that Apollo Client does not have problems.
I forgot to set SameSite attribute to None for cross-origin request. Recently Google Chrome have changed these behavior.
Hope this will be of some help 👍

I think I understand what's happening. The client and server I'm working with are both subdomains of herokuapp (e.g.., ui.herokuapp.com and web-server.herokuapp.com).

Ahh yes! Im on localhost:3000 for my server and localhost:8080 for my front end!
Makes sense why cookies get set when I use the graphql interface at localhost:3000/graphql and not on 8080.

I will have to figure that out.

Had a similar issue talking to an API Gateway lambda Apollo server. I turned off CORS in Apollo server itself as have let API Gateway take care of that, but I had Access-Control-Allow-Headers: * set there. This comes through correctly on the browser as * but it seems Apollo client possibly doesn't like it. Setting API Gateway settings to Access-Control-Allow-Headers: content-type and all of a sudden the client works and is sending the cookies correctly.

Disclaimer: I haven't dug into the root cause here and may even just be my own misunderstanding of CORS, but hope it helps someone as I was stuck on this for days!

Hello everybody from 2021, and... I'm having the same issue ((

yup, having the same error

Hello @cyc1e from 2021 - we have been using my this in production since 2020, see the gist above for the implementation.

I ended up using Axios to make my queries. Its a hell of a learning curve using axios to run graph queries but now I have a product that works and businesses are using it :)

To be honest rest would have been way easier and quicker but we implemented graph in our back-end and pushed through with it. Its time consuming.

There is a lot of history in this issue, and the problems listed head in all sorts of different directions. If anyone thinks this is still a problem in @apollo/client@latest, and can provide a small runnable reproduction, we'll take a closer look. Thanks!

Hi guys, same problem. It works in browser, but not on server side.

@apollo/client ^3.0.2
next@10.2.0

Apollo client credentials:

    const { HttpLink } = require('@apollo/client/link/http')
    return new HttpLink({
      uri: 'http://localhost:3000/api/graphql',
      credentials: 'same-origin',
    })

I can read the cookies in getServerSideProps but not from the Apollo-client call.

I'm using this example, you may use that to reproduce as it has the same issue.

https://github.com/vercel/next.js/tree/canary/examples/api-routes-apollo-server-and-client-auth

Try to use getServerSideProps to get data from a protected resolver.

I hope it helps.

@allanesquina @apollo/client@3.0.2 is a fairly old version of AC3; can you try with @apollo/client@latest? If that doesn't work, can you provide a small runnable reproduction that clearly demonstrates the issue you're seeing? The link you provided is for one of Next's demo apps. To be able to properly troubleshoot this, we'll need a focused reproduction that shows the problem. Thanks!

@hwillson I did some tests and I realized that the SchemaLink used to avoid network on SSR was missing the context.

 return new SchemaLink({ schema, context: { { req, res } })

So I'm passing the context all way down in getServerSideProps.

export async function getServerSideProps(context) {
  const client = initializeApollo(null, context);
...
}

The client.js file

import { useMemo } from "react";
import { ApolloClient, InMemoryCache } from "@apollo/client";
import merge from "deepmerge";

let apolloClient;

function createIsomorphLink(ctx) {
  if (typeof window === "undefined") {
    const { SchemaLink } = require("@apollo/client/link/schema");
    const { schema } = require("./schema");
    return new SchemaLink({ schema, context: ctx });
  } else {
    const { HttpLink } = require("@apollo/client/link/http");
    return new HttpLink({
      uri: "/api/graphql",
      credentials: "same-origin",
    });
  }
}

function createApolloClient(ctx) {
  return new ApolloClient({
    ssrMode: typeof window === "undefined",
    link: createIsomorphLink(ctx),
    cache: new InMemoryCache(),
  });
}

export function initializeApollo(initialState = null, ctx) {
  const _apolloClient = apolloClient ?? createApolloClient(ctx);

  // If your page has Next.js data fetching methods that use Apollo Client, the initial state
  // get hydrated here
  if (initialState) {
    // Get existing cache, loaded during client side data fetching
    const existingCache = _apolloClient.extract();

    // Merge the existing cache into data passed from getStaticProps/getServerSideProps
    const data = merge(initialState, existingCache);

    // Restore the cache with the merged data
    _apolloClient.cache.restore(data);
  }
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === "undefined") return _apolloClient;
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient;

  return _apolloClient;
}

export function useApollo(initialState) {
  const store = useMemo(() => initializeApollo(initialState), [initialState]);
  return store;
}

It solves the issue using the SchemaLink but I couldn't make it work with HttpLink on server side. Maybe if I create a custom header on ApolloClient with Set-Cookie property to propagate the cookie but I'm not sure if it's gonna work.

Just an update: I'm using @apollo/client: latest now.

Heyo! I was running into the issue of apollo-client sending / setting cookies client side fine, but was getting problems with it server side. I use an afterware server-side to set cookies. Here's my fix with typescript:

import {
  ApolloClient, ApolloLink, HttpLink, InMemoryCache, gql,
} from '@apollo/client';
import { NormalizedCacheObject } from '@apollo/client/cache';
import { GetServerSidePropsContext } from 'next';
import { useMemo } from 'react';

const createClient = (ctx?: GetServerSidePropsContext) => {
  const setCookiesAfterware = new ApolloLink((operation, forward) => forward(operation).map((response) => {
    ctx?.res.setHeader('set-cookie', operation.getContext().response.headers.raw()['set-cookie'] || '');
    return response;
  }));

  return new ApolloClient({
    link: setCookiesAfterware.concat(new HttpLink({ uri: 'http://localhost/graphql', headers: { cookie: ctx.req.headers.cookie } })),
    cache: new InMemoryCache(),
  });
};

let client: ApolloClient<NormalizedCacheObject> | undefined;
const initializeClient = (initialState?: NormalizedCacheObject, ctx?: GetServerSidePropsContext) => {
  const apolloClient = client ?? createClient(ctx);

  if (initialState) {
    const prevState = apolloClient.extract();

    apolloClient.restore({ ...prevState, ...initialState, ...{ ROOT_QUERY: { ...prevState.ROOT_QUERY, ...initialState.ROOT_QUERY } } });
  }

  if (typeof window === 'undefined') return apolloClient;

  client ??= apolloClient;

  return client;
};

const useClient = (initialState?: NormalizedCacheObject) => useMemo(() => initializeClient(initialState), [initialState]);
const getClient = (ctx: GetServerSidePropsContext) => initializeClient(undefined, ctx);

export { gql, useClient };
export default getClient;

Thx @rag4214, now it made sense, I have to set the headers to forward the cookies to the API.

Heyo! I was running into the issue of apollo-client sending / setting cookies client side fine, but was getting problems with it server side. I use an afterware server-side to set cookies. Here's my fix with typescript:

import {
  ApolloClient, ApolloLink, HttpLink, InMemoryCache, gql,
} from '@apollo/client';
import { NormalizedCacheObject } from '@apollo/client/cache';
import { GetServerSidePropsContext } from 'next';
import { useMemo } from 'react';

const createClient = (ctx?: GetServerSidePropsContext) => {
  const setCookiesAfterware = new ApolloLink((operation, forward) => forward(operation).map((response) => {
    ctx?.res.setHeader('set-cookie', operation.getContext().response.headers.raw()['set-cookie'] || '');
    return response;
  }));

  return new ApolloClient({
    link: setCookiesAfterware.concat(new HttpLink({ uri: 'http://localhost/graphql', headers: { cookie: ctx.req.headers.cookie } })),
    cache: new InMemoryCache(),
  });
};

let client: ApolloClient<NormalizedCacheObject> | undefined;
const initializeClient = (initialState?: NormalizedCacheObject, ctx?: GetServerSidePropsContext) => {
  const apolloClient = client ?? createClient(ctx);

  if (initialState) {
    const prevState = apolloClient.extract();

    apolloClient.restore({ ...prevState, ...initialState, ...{ ROOT_QUERY: { ...prevState.ROOT_QUERY, ...initialState.ROOT_QUERY } } });
  }

  if (typeof window === 'undefined') return apolloClient;

  client ??= apolloClient;

  return client;
};

const useClient = (initialState?: NormalizedCacheObject) => useMemo(() => initializeClient(initialState), [initialState]);
const getClient = (ctx: GetServerSidePropsContext) => initializeClient(undefined, ctx);

export { gql, useClient };
export default getClient;

This worked for me. Thanks @rag4214

Add cookie to getServerSideProps on a page by page basis

Easy quick method to add cookie is to pass context.

export async function getServerSideProps(context) {
  const user = await client.query({
    query: GET_COOKIE_USER,
    context: {
      headers: {
        cookie: context.req.headers.cookie
      }
    }
  });

  return {
    props: {
      user: user.data.currentUser
    }
 };
}

If client side is not storing cookie on login or whatever

adding credentials property seems to do the trick

const httpLink = new HttpLink({ 
  uri: "http://localhost:3000/graphql",
  credentials: 'include' // allows cookies
});

The docs are here:
https://www.apollographql.com/docs/react/networking/authentication/#cookie

Add cookie to getServerSideProps on a page by page basis

Easy quick method to add cookie is to pass context.

@gregg-cbs I believe this is what we want to avoid (although this is what I do now). Repetitive code in many pages is a bad practice. Need to find a solution for this.

@alanyong91 We definitely want cookies to be something that happens naturally.
But unfortunately thats what I could offer to those who are desperate and need cookies to make requests.

What solutions can you think of that would be good to try? I think together as a community we can come up with an ideal solution and if not make it ourselves we can propose it to next and or apollo.

Guys the problem that we are new to Next.js or any SSR (server side rendering) you guys are using.
For example my SSR code was calling an Apollo query which needs to send a cookie for authentication to access data, This is totally stupid and doesn't make any sense. All the queries in the SSR side should only ask for public data (queries don't need any type of authentication or sending cookies).

This is example with nextjs apollo ssr codegen,

 const {
    props: { apolloState, data, error },
  } = await ssrGetOwnSettings.getServerPage(
    { variables: { where: { id } } },
    context,
  );

initiate client,

const createApolloClient = (context: Context) => {
  return new ApolloClient({
    cache: new InMemoryCache(),
    connectToDevTools: isDevelopment,
    ssrMode: typeof window === 'undefined',
    link: createHttpLink({
      uri: `${appConfig.baseUrl}${appConfig.apiUrl}`,
      headers: { cookie: context?.req?.headers.cookie },
    }),
  });
};

I try almost everything, but it still doesn't work for me... I can only making work with httponly = false cookie :

//ApolloClient
  const httpLink = createHttpLink({
    uri: API_URL,
  });

 
  const authLink = setContext((_, { headers }) => {
    // This work only with httpOnly = false
    const token = Cookies.get('token')
   
    // return the headers to the context so httpLink can read them
    return {
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : "",
      }
    }
  });
  
  const client = new ApolloClient({
    link: authLink.concat(httpLink),
    cache: new InMemoryCache(),
  });

If I try to add credentials:"include" to my httpLink, I get : The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

I setup my cookie using /api/login

const data = await strapiRes.json();
    if (strapiRes.ok) {
      // Set Cookie
      res.setHeader(
        "Set-Cookie",
        cookie.serialize("token", data.jwt, {
          httpOnly: false,
          secure: process.env.NODE_ENV !== "development",
          maxAge: 60 * 60 * 24 * 7, // 1 week
          sameSite: "strict",
          path: "/",
        })
      );

@Kaherdin yes, that's an HTTP security limitation—your server can't send the wildcard * for the allowed origin if you want it to accept cookies.

One solution (not the most secure) is to pass true instead of * as the origin setting for the cors middleware in your node server that's running Apollo Server:

app.use(cors({
    credentials: true,
    // allow all origins
    origin: true,
}))

The more secure way is to check the origin against a whitelist, as explained here:
https://www.npmjs.com/package/cors#configuring-cors-w-dynamic-origin

I also found that in my case, since I'm using apollo-server-express, I had to pass in the corsOptions to the applyMiddleware function instead of using cors on the express server directly, or else it wasn't picking them up. I'm not sure if this is necessary on the latest version, but in any case this is what worked for me:

const corsOptions = {
    credentials: true,
    // allow all origins
    origin: true,
}

apolloServer.applyMiddleware({
    app: server,
    cors: corsOptions,
})

In my case I was using a custom link and had to add custom fetchOptions in it:

const httpLink = new HttpLink({
  uri: "http://localhost:4000/query",
  fetchOptions: {
    credentials: "include",
  },
});
const link = from([errorLink, httpLink]);
const graphqlClient = new ApolloClient({
  link,
  cache: new InMemoryCache(),
  credentials: "include",
});

@dclipca FYI I think that because you're using a custom link, the second credentials: "include" (the one you're passing directly to ApplloClient) is not needed.

My problem was with Apollo Studio. Solution for me was a combination of the following.

index.ts (in apollo server):

import * as cookieParser from "cookie-parser";

const startServer = async () => {  
    const app = express();
    app.use(cookieParser());
    
        let corsOptions = { 
        origin: "https://studio.apollographql.com",
        credentials: true,
      };
      
          const server = new ApolloServer({ 
        schema: genSchema() as any,
        context: ({req, res}) => { 
            return {
                 req,
                 res
            }
        }, 
    });
      
      await server.start();
    server.applyMiddleware({ app, cors: corsOptions }); 

In resolver response that sets the token:

context.res.cookie('token', response.accessToken, { secure: true, sameSite: 'None', httpOnly: true, maxAge: 60000000 });

Studio Settings:

image

For a bit more context, I'm experiencing this specifically in Safari (15.5), w/ "Prevent cross-site tracking" enabled, while doing local development on http://myapp.local. My GraphQL API is served from the domain http://api.myapp.local. The cookies are assigned the domain .myapp.local

Doing either of the following DOES work:

  • Use Chrome/Firefox
  • Disable "Prevent cross-site tracking"

I realize a number of the comments on this issue are likely about diverging issues, with many being simply misconfiguration issues. But I suspect a number of people are experiencing this issue due to some combination of issues with Safari's cookie protection, sub-domains, and maybe Apollo itself?

I had a similar kind of issue where cookies were not being sent along with all the requests even tho cookies were stored in the browser. On localhost everything was working fine but things were different for staging environment since the staging frontend and backend urls were comprised of different subdomains and for cookie to be available I had to setup domain and path in cookie explicitly

Suppose your frontend and backend url are like thesewww.frontend.example.com and www.backend.example.com respectively. So your cookie should have the information about path and domain

response.cookie( 'xyz', 1234, { sameSite: 'lax', httpOnly: true, path: / domain: .example.com, // make sure to start domain with a dot . } );

@huzaifaali14 it has already been written here many times

#4190 (comment)

I had the same problem.

My solution was the following (I did not find a place where I could clarify it, but it was a trial and error)

Apollo client config:

import {ApolloClient, HttpLink, InMemoryCache} from "@apollo/client";

const httpLink = new HttpLink({
  uri: `${process.env.NEXT_PUBLIC_URL_SITE}/api/graphql`,
  credentials: "same-origin",
});

export const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
});

SSR request (typescript):

export const getServerSideProps: GetServerSideProps = async ({req}) => {
    const {data} = await client.query({
      query: QUERY_NAME,
      context: {
        headers: {
          cookie: req?.headers?.cookie ?? null,
        },
      },
    });
  
    return {
      props: {data},
    };
  };

I'm using:

  • "@apollo/client": "^3.7.1",
  • "@apollo/server": "^4.1.1",
  • "graphql": "^16.6.0",
  • "next": "13.1.1",
  • "react": "18.2.0",

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
For general questions, we recommend using StackOverflow or our discord server.