nerdycoder007
nerdycoder007

Reputation: 71

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

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

Upvotes: 7

Views: 13669

Answers (2)

Richard Vargas
Richard Vargas

Reputation: 71

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;

Upvotes: 7

d00dle
d00dle

Reputation: 1316

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.

Upvotes: 0

Related Questions