Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphQL API rate/complexity limits #381

Closed
michaelbromley opened this issue Jun 18, 2020 · 4 comments
Closed

GraphQL API rate/complexity limits #381

michaelbromley opened this issue Jun 18, 2020 · 4 comments

Comments

@michaelbromley
Copy link
Member

michaelbromley commented Jun 18, 2020

Is your feature request related to a problem? Please describe.
Due to the flexible nature of GraphQL, it is possible to create queries that end up being very expensive for the server to execute, for example:

{
  products(options: { take: 1}) {
    items {
      facetValues {
        id
        facet {
          values {
            facet {
              values {
                facet {
                  values {
                    facet {
                      id
                      name 
                      translations {
                        id
                        languageCode
                        name
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

The above query takes 15 seconds to resolve on my fairly beefy laptop (and also returns a 825kb response)

Imagine now we have take: 100 rather than take: 1. There goes the whole server!

So the problem comes down to 2 potential risks:

  1. Poor performance due to accidentally-expensive queries by the developer
  2. Malicious attacks used to cause a denial-of-service by overwhelming the server with a request like the one above.

Describe the solution you'd like
There several strategies to mitigate these risks, which are well-described in this StackOverflow answer and thread.

Also see suggestions here: apollographql/apollo-server#1310

The measures range from fairly simple (timeouts) to more complex, e.g. analyzing individual queries to compute a complexity score.

This thread will track further research into the topic and proposals on what to build in to Vendure core to give at least some protection from the above by default.

@michaelbromley
Copy link
Member Author

graphql-query-complexity looks to be a good solution for limiting too-deeply-nested queries. It looks well-maintained, only has 1 tiny dependency, and is quite widely downloaded on npm (80k / week)

There is an example here of integrating it with Apollo Server 2 as an ApolloServerPlugin

We could build a similar plugin and ship it with core, and users can import it as needed. It would have to be well-documented in the "deployment" docs as a recommendation for production deploys.

@michaelbromley
Copy link
Member Author

For rate-limiting and timeouts we can make use of the vast Express ecosystem, since Vendure allows you to plug in any Express middleware quite trivially.

So now I'm thinking it makes sense to keep all of this out of core, and instead have a separate "production-ready" plugin which configures things like:

michaelbromley added a commit that referenced this issue Jul 6, 2020
@michaelbromley
Copy link
Member Author

Added docs on this for now, and will defer any other implementation to a later point.

@michaelbromley michaelbromley removed this from the v0.14.0 milestone Jul 14, 2020
@michaelbromley michaelbromley unpinned this issue Sep 2, 2020
@michaelbromley
Copy link
Member Author

This is handled by the HardenPlugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant