apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

Cookies not sent on calls to other domains despite `credentials: 'include'` setting.

Open stijn-gravity opened this issue 1 year ago • 1 comments

Intended outcome: On my local environment everything works as expected. My cookie JWT is sent with every request to my apollo server.

Actual outcome: But when I deploy to my development server things stop working. This is likely caused by CORS settings, but I could not find where I went wrong.

How to reproduce the issue: Relevant client code:

  const httpLink = createHttpLink({
    uri: getEndpointUri(),
    credentials: 'include',
    fetch: !isBrowser ? fetch : undefined,
  });

Relevant server code:

export function corsHandler() {
  const whitelist: string[] =
    process.env.DOMAIN_WHITELIST_CORS?.split(';') || [];

  const corsOptions: cors.CorsOptions = {
    origin: (origin, callback) => {
      if (!origin || process.env.CORS_OPTIONAL) {
        return callback(null, origin);
      }

      if (isInternalDeployment()) {
        return callback(null, origin);
      }

      if (whitelist.includes(origin)) {
        return callback(null, origin);
      }

      return callback(new ApolloError(`Url ${origin} Not allowed by CORS`));
    },
    credentials: true,
  };

  return cors(corsOptions);
}

const app = express();
app.use(corsHandler());

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context,
  cache,
  introspection:
    process.env.DEPLOYMENT_ENV === 'development' ||
    process.env.DEPLOYMENT_ENV === 'local' ||
    process.env.DEPLOYMENT_ENV === 'test',
  apollo: {
    graphId: 'gv-academy',
    key: process.env.ENGINE_API_KEY,
    graphVariant: process.env.APOLLO_SCHEMA_TAG,
  },
  dataSources,
  mocks: process.env.NODE_ENV === 'test',
  plugins,
});

async function startServer() {
  try {
    await server.start();

    server.applyMiddleware({
      app,
      path: '/',
      cors: {
        origin: corsWhitelist,
        credentials: true,
      },
    });
  } catch (e) {
    // eslint-disable-next-line no-console
    console.error(e);
    process.exit();
  }
  return server;
}

app.listen(port, async () => {
  await startServer();
  // eslint-disable-next-line no-console
  console.log(
    `🛸 Server ready at http://localhost:${port}${server.graphqlPath}`
  );
});

Versions Everything is running at the latest stable versions.

stijn-gravity avatar Aug 25 '22 11:08 stijn-gravity

Same issue and same client configuration. I excluded my server configuration because I can succeed with a manual fetch() request.

I think it's come from the client not passing fetch : credentials: 'include'

nebnes avatar Sep 02 '22 13:09 nebnes

Hi @stijn-gravity 👋🏻 thanks for opening this issue! I think more information is needed to understand whether this is an issue in the Apollo Client source code, such as where the JWT is being included and what the actual HTTP requests look like in development vs. deployed environments. A running reproduction is best :)

bignimbus avatar Nov 05 '22 02:11 bignimbus