Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

apollo-server-express CORS issue

So I am migrating to apollo-server-express 2.3.3 ( I was using 1.3.6 ) I've followed several guides, making the necessary tweaks but am stuck in a CORS issue.

According to the docs you have to use the applyMiddleware function to wire up the apollo server with express.

I am currently doing the following:

const app = express();

// CORS configuration

const corsOptions = {
    origin: 'http://localhost:3000',
    credentials: true
}

app.use(cors(corsOptions))

// Setup JWT authentication middleware

app.use(async (req, res, next) => {
    const token = req.headers['authorization'];
    if(token !== "null"){
        try {
            const currentUser = await jwt.verify(token, process.env.SECRET)
            req.currentUser = currentUser
        } catch(e) {
            console.error(e);
        }
    }
    next();
});

const server = new ApolloServer({ 
    typeDefs, 
    resolvers, 
    context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});

server.applyMiddleware({ app });


const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
})

For some reason my express middleware doesn't seem to be executing, when I try to do a request from localhost:3000 (client app) I get the typical CORS error

With apollo-server-express 1.3.6 I was doing the following without no issues:

app.use(
    '/graphql',
    graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }),
    bodyParser.json(),
    graphqlExpress(({ currentUser }) => ({
        schema,
        context: {
            // Pass Mongoose models
            Property,
            User,
            currentUser
        }
    }))
);

Now with the new version, event though the docs make this look like a straightforward migration, I don't seem to be able to make it work. I've checked various articles and no one seems to be having the issue.

like image 256
José Del Valle Avatar asked Feb 01 '19 18:02

José Del Valle


People also ask

How do I enable CORS in Apollo server?

You can enable credentials with CORS by setting the Access-Control-Allow-Credentials HTTP header to true . You must specify an origin to enable credentialed requests. If your server sends the * wildcard value for the Access-Control-Allow-Origin HTTP header, your browser will refuse to send credentials.

Is Apollo server based on express?

The batteries-included apollo-server library uses apollo-server-express under the hood.

What are Cors errors?

The CORS behavior, commonly termed as CORS error, is a mechanism to restrict users from accessing shared resources. This is not an error but a security measure to secure users or the website which you are accessing from a potential security bleach.


2 Answers

From my understanding of the Apollo Server middleware API, CORS options, body-parser options and the graphql endpoint are treated as special entities that must be passed directly to the applyMiddleware param object.

So you want to try the following configuration:

const app = express();

// CORS configuration
const corsOptions = {
    origin: 'http://localhost:3000',
    credentials: true
}

// The following is not needed, CORS middleware will be applied
// using the Apollo Server's middleware API (see further below)
// app.use(cors(corsOptions))

// Setup JWT authentication middleware
app.use(async (req, res, next) => {
    const token = req.headers['authorization'];
    if(token !== "null"){
        try {
            const currentUser = await jwt.verify(token, process.env.SECRET)
            req.currentUser = currentUser
        } catch(e) {
            console.error(e);
        }
    }
    next();
});

const server = new ApolloServer({ 
    typeDefs, 
    resolvers, 
    context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});

// There is no need to explicitly define the 'path' option in
// the configuration object as '/graphql' is the default endpoint
// If you planned on using a different endpoint location,
// this is where you would define it.
server.applyMiddleware({ app, cors: corsOptions });

const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
})
like image 123
Thomas Hennes Avatar answered Oct 19 '22 08:10

Thomas Hennes


With Apollo Server 2.x you supply the cors field in the constructor of ApolloServer.

So in your case, it should look like the following:

const corsOptions = {
    origin: 'http://localhost:3000',
    credentials: true
}

// Setup JWT authentication middleware

app.use(async (req, res, next) => {
    const token = req.headers['authorization'];
    if(token !== "null"){
        try {
            const currentUser = await jwt.verify(token, process.env.SECRET)
            req.currentUser = currentUser
        } catch(e) {
            console.error(e);
        }
    }
    next();
});

const server = new ApolloServer({ 
    typeDefs, 
    cors: cors(corsOptions),
    resolvers, 
    context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});

server.applyMiddleware({ app });


const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
})

Here you find all params accepted by the apollo server: https://www.apollographql.com/docs/apollo-server/api/apollo-server.html#Parameters-2

Here you find the relevant discussion: https://github.com/apollographql/apollo-server/issues/1142

like image 8
Ric0 Avatar answered Oct 19 '22 07:10

Ric0