UNPKG

@graphql-yoga/plugin-csrf-prevention

Version:

CSRF prevention plugin for GraphQL Yoga that requires the clients to have a specific header set.

47 lines (46 loc) 1.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useCSRFPrevention = useCSRFPrevention; const graphql_yoga_1 = require("graphql-yoga"); const NON_PREFLIGHTED_CONTENT_TYPES = [ 'application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain', ]; /** * If you have CORS enabled, almost all requests coming from the browser will have a * preflight request - however, some requests are deemed "simple" and don't make a preflight. * * One example of such a request is a good ol' GET request without any headers, this request can * be marked as "simple" and have preflight CORS checks skipped therefore skipping the CORS check. * * This attack can be mitigated by saying: "all GET requests must have a custom header set". This * would force all clients to manipulate the headers of GET requests, marking them as "_not-_simple" * and therefore always executing a preflight request. */ function useCSRFPrevention(options = {}) { const { requestHeaders = ['x-graphql-yoga-csrf'] } = options; return { onRequestParse({ request }) { if (wasTheRequestAlreadyPreflightChecked(request.headers?.get('content-type'))) { return; } if (requestHeaders.some(headerName => request.headers.has(headerName))) { return; } throw (0, graphql_yoga_1.createGraphQLError)('Required CSRF header(s) not present', { extensions: { http: { status: 403, }, }, }); }, }; } const wasTheRequestAlreadyPreflightChecked = (contentType) => { if (!contentType) { return false; } return !NON_PREFLIGHTED_CONTENT_TYPES.some(nonPreflightContentType => contentType.toLowerCase().startsWith(nonPreflightContentType)); };