GraphQL Security

Webonyx-GraphQL provides query analysis to reject complex queries to your GraphQL server. This is used to protect GraphQL servers against resource exhaustion and DoS attacks.

Query Complexity

Query complexity is one of the possible ways to reject GraphQL requests. The idea is to define how complex each field is by using a simple number. By default, each field has a query complexity of 1.

type StoreList {           # complexity: 1
    name: String           # complexity: 1
    is_active: Boolean     # complexity: 1
    base_link_url : String # complexity: 1
    base_url : String      # complexity: 1
    code: String           # complexity: 1
}

In the example, we can see that if the request contains all fields from type StoreList, then it will consume 6 of query complexity. For this case, if the GraphQL server is set to limit query complexity to 3, it will return a response with the message: "Max query complexity should be 3 but got 6."

How to increase Query Complexity limits

It is strongly recommended to not increase Query Complexity limits because it will weaken the security of your website.

Sometimes we need to get new fields in the same request to implement a new feature on the website. This leads to situations where it would be very complex to implement the feature without increasing limits. In this case, it is necessary to slightly increase the limit in the Query Complexity rule. In ScandiPWA, the Query Complexity rule number is set in the ScandiPWA_CatalogGraphQL module. It can be checked in the file '/src/etc/di.xml' .

<type name="Magento\Framework\GraphQl\Query\QueryComplexityLimiter">
    <arguments>
        <argument name="queryComplexity" xsi:type="number">VALUE</argument>
    </arguments>
</type>

To increase limits, we need to create Magento module and extend ScandiPWA_CatalogGraphQL where it will be possible to set a new rule.

If the project already includes an extended ScandiPWA_CatalogGraphQL, it is better to increase the query complexity value there.

Steps to create and increase limits: 1. Create a simple Magento module with the name "GraphQLQueryComplexity" or any other you wish. 2. In the file 'etc/module.xml' , add ScandiPWA_CatalogGraphQL as below:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="ScandiPWA_GraphQlQueryComplexity">
        <sequence>
            <module name="ScandiPWA_CatalogGraphQl"/>
        </sequence>
    </module>
</config>

3. Create the file 'etc/di.xml' where the Query Complexity rule will be changed.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\GraphQl\Query\QueryComplexityLimiter">
        <arguments>
            <argument name="queryComplexity" xsi:type="number">YOUR VALUE</argument>
        </arguments>
    </type>
</config>

How to troubleshoot

To get beyond Query Complexity Rule limits, it is necessary to detect this problem at the stage of developing the project. By default, Magento enables query complexity rule only on production mode, which means that when the project is in development mode GraphQL won't reject a request even if it is above the set rule.

For this reason, ScandiPWA changes Magento's default behavior by enabling query complexity rule in development mode and showing query complexity in each response that the user sends to the server.

Starting only from version "3.0.2" of module ScandiPWA_PersistedQuery is it possible to see query complexity on request and enabled rule in development mode.

To see how much Query complexity is requested, we need to open browser tools and check the response of the request. In the section of "Response Headers", it is easy to find a field with the name "query-complexity" where its value is the "cost" of your request.

This will help to check the query complexity before getting errors about it and see how close it is to limits.

Last updated