Apollo Client "This operation has been blocked as a potential Cross-Site Request Forgery (CSRF)"
Asked Answered
I

2

6

I am using nextJS and apollo client, and I am creating a mutation which needs to send image and a file.

But when I try to make a request the error shows up. This operation has been blocked as a potential Cross-Site Request Forgery (CSRF) . I had created same mutation in v3 of @apollo/server, but there was no such error. This may be some v4 problem.

My apollo client setup :

Client Setup

The error :

Error

Apollo v4 server setup:

Server Setup

As per apollo docs

By default, Apollo Server 4 has a CSRF prevention feature enabled. This means your server only executes GraphQL operations if at least one of the following conditions is true:

Apollo Docs

Intrusive answered 26/11, 2022 at 9:33 Comment(1)
Added v4 solutionVillanelle
A
7

In the Apollo Client configuration add:

{headers: {'Apollo-Require-Preflight': 'true'}} to createUploadLink

Looks like:

import { ApolloClient, InMemoryCache } from "@apollo/client";
import { createUploadLink } from "apollo-upload-client";
import { setContext } from "apollo-link-context";

// const httpLink = createHttpLink({
//     uri: 'http://localhost:4000/graphql',
// })
const middlewareUpdate = createUploadLink({ uri: process.env.SERVER });
const authLink = setContext((_, { headers }) => {
  // Leer el storage almacenado
  const token = localStorage.getItem("token");
  // console.log(token);
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
      'Apollo-Require-Preflight': 'true'
    },
  };
});

const Client = new ApolloClient({
  connectToDevTools: true,
  link: authLink.concat(middlewareUpdate),
  
  fetchOptions: {
    mode: "no-cors",
  },
});

export default Client;
Adopted answered 11/1, 2023 at 20:30 Comment(0)
V
0

ApolloServer enables you to provide your own CORS configuration directly in the constructor.

Since there is many ways to setup and construct your Apollo server, you should look up the correct way for your stack.

You can read more about Configuring CORS in Apollo on their website.

This is how I do it for version 3 of apollo-server:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  ...
  cors: {
    origin: true,
    credentials: true, // true if you need cookies/authentication
    methods: ['GET', 'POST', 'OPTIONS'],
  },
})

Apollo version 4

Apollo removed support for CORS in their ApolloServer class and solely relies on Express now if you need to use middleware, CORS included.

It would look something like this

import { ApolloServer } from '@apollo/server'
import { expressMiddleware } from '@apollo/server/express4'
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'
import express from 'express'
import http from 'http'
import cors from 'cors'
import bodyParser from 'body-parser'

const app = express()
const httpServer = http.createServer(app)

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    ApolloServerPluginDrainHttpServer({ httpServer }),
  ],
})
await server.start()

app.use(
  cors({
    methods: ['GET', 'POST', 'OPTIONS'],
    credentials: true,
    maxAge: 600,
    origin: [
      'http://example.com',
      'https://studio.apollographql.com'
    ],
  }),
  bodyParser.json(),
  expressMiddleware(server, {
    context: async ({ req, res }) => {
      return {}
    }
  })

await new Promise<void>((resolve) => httpServer.listen({ port: 4000 }, resolve))
console.log(`🚀 GraphQL server is ready`)

Note: Please always post the code directly into StackOverflow, as screenshots are hard for people to work with.

Villanelle answered 26/11, 2022 at 13:32 Comment(2)
Thanks for your solution. Yes, this works in version 3 of apollo-server but in the version 4, it's not working.Intrusive
I also tried, the solution for Apollo v4 doesn't work, unfortunately.Libelous

© 2022 - 2024 — McMap. All rights reserved.