Comments (7)
Have you read the docs about the CSRF prevention feature, including the specific section about graphql-upload
? https://www.apollographql.com/docs/apollo-server/security/cors/#preventing-cross-site-request-forgery-csrf
from apollo-server.
I'm trying to understand this topic but the documentation is too confusing for me. I need a simple example to follow along. This is the code I wrote but it's not working as expected. Can you please take a look and tell me what I'm doing wrong? I'm really stuck and frustrated. Thanks for your help.
import { createWriteStream, unlink } from "fs";
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import express from "express";
import pkg from "body-parser";
import cors from "cors";
import mkdirp from "mkdirp";
import shortid from "shortid";
import { schema } from "./schema.js";
import dotenv from "dotenv";
dotenv.config();
const app = express();
const { json } = pkg;
const UPLOAD_DIR = "./uploads";
// Ensure upload directory exists.
mkdirp.sync(UPLOAD_DIR);
/**
* Stores a GraphQL file upload. The file is stored in the filesystem and its
* metadata is recorded.
* @param {GraphQLUpload} upload GraphQL file upload.
* @returns {object} File metadata.
*/
const storeUpload = async (upload) => {
console.log("####upload###");
const { createReadStream, filename, mimetype } = await upload;
const stream = createReadStream();
const id = shortid.generate();
const path = `${UPLOAD_DIR}/${id}-${filename}`;
const file = { id, filename, mimetype, path };
await new Promise((resolve, reject) => {
stream
.on("error", (error) => {
unlink(path, () => {
reject(error);
});
})
.pipe(createWriteStream(path))
.on("error", reject)
.on("finish", resolve);
});
return file;
};
const server = new ApolloServer({
csrfPrevention: false,
schema,
context: { storeUpload },
});
await server.start();
const PORT = 5031;
app.use("/graphql", cors(), json(), expressMiddleware(server));
app.listen(PORT, () => {
console.log(`File Server listening on port ${PORT}/graphql`);
});
from apollo-server.
The change you need to make is in your client. The protocol designed for graphql uploads contains a severe vulnerability for any server that uses cookies to authenticate, unless both the server and client work together to avoid the security issue. (This vulnerability will allow any website on the internet to get browsers to run mutations against your server with the visitor's cookies, even if your server tries to use CORS to restrict your API's usage to trusted servers.)
Apollo Server works by default to prevent this problem; you need to configure your client to work with it. What package are you using to implement GraphQL uploads on the client side?
(You should not add csrfPrevention: false
to your server unless you are 100% positive you understand the CSRF threat model intimately and your server is not vulnerable to it.)
from apollo-server.
For mutation, I am using GraphQLUpload here is the code, I am using Graphaql Playground to test my upload for my client.
import { GraphQLList, GraphQLObjectType, GraphQLNonNull } from "graphql";
import GraphQLUpload from "graphql-upload/GraphQLUpload.mjs";
import { FileType } from "./File.js";
export const MutationType = new GraphQLObjectType({
name: "Mutation",
fields: () => ({
singleUpload: {
description: "Stores a single file.",
type: new GraphQLNonNull(FileType),
args: {
file: {
description: "File to store.",
type: new GraphQLNonNull(GraphQLUpload),
},
},
resolve: (parent, { file }, { storeUpload }) => storeUpload(file),
},
multipleUpload: {
description: "Stores multiple files.",
type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(FileType))),
args: {
files: {
description: "Files to store.",
type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLUpload))),
},
},
async resolve(parent, { files }, { storeUpload }) {
const uploadedFiles = [];
for (const file of files) {
try {
const uploadedFile = await storeUpload(file);
uploadedFiles.push(uploadedFile);
} catch (error) {
console.error(`${error.name}: ${error.message}`);
}
}
return uploadedFiles;
},
},
}),
});
from apollo-server.
That's server code still. I don't know if graphql-playground can be adapted to use the better protocol (last I checked the project had been explicitly unmaintained for years).
from apollo-server.
Sorry, I am using Introspection and not graphql-playground.
from apollo-server.
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.
from apollo-server.
Related Issues (20)
- subscription callback support - update to latest version
- Timeout Plugin for each request HOT 3
- AS4 contains code that makes triggering a crashing bug in [email protected] (fixed in 16.7) more likely HOT 8
- 'graphqlError.extensions' is possibly 'undefined' in enrichError() HOT 2
- Docs - Inconsistency when wrapping content inside some tables HOT 1
- ENOENT: no such file or directory, open './schema.graphql' HOT 1
- schemaReporter pollTimer has incorrect type HOT 1
- Error from resolver without extensions[V3 was not adding extensions in any error type from resolvers] HOT 2
- Integration of AS4 with graphql-jit not working HOT 3
- Bun integration on subscription (Query and Mutation Works, but not Subscription) HOT 3
- TypeSafe Custom GQLError HOT 2
- support for fastify version 4 HOT 2
- Allow passing http2 server to ApolloServerPluginDrainHttpServer
- ApolloServerPluginUsageReporting reportTimer has incorrect type HOT 1
- Elasticache cluster - CROSSLOT Keys in request don't hash to the same slot HOT 4
- Unable to package/deploy with serverless using Node14 and apollo-serverless-core HOT 3
- ApolloServerPluginUsageReporting does not allow to pass http agent HOT 11
- Misconfigured `sendVariableValues` results in similar behavior as `{all: true}` HOT 3
- ApolloServerPluginUsageReporting does not allow to pass http agent HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from apollo-server.