Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GraphQL - Security - Protect nested data

Let's assume my app is an e-commerce. There are Users, Orders and Products.

You need to be authenticated (with JWT Token) to have access to your user data, and your orders. This check is done in resolvers.

However, Products are public. You can see products without being logged in.

Of course, a User has Orders, and an Order has Products

What if someone in the frontend is doing this query:

query IAmEvil {
  products {
    orders {
      users {
         id
         name
         email
       }
    }
  }
}

This guy, not authenticated will have access to users data. How Can I prevent that?

Do I have to add rules in all my resolvers for all nested queries?

related Documentation:

https://www.apollographql.com/docs/guides/security.html https://www.howtographql.com/advanced/4-security/ https://blog.apollographql.com/securing-your-graphql-api-from-malicious-queries-16130a324a6b https://www.prisma.io/forum/t/graphql-security-protect-nested-data/4519

like image 871
Alan Avatar asked Jun 12 '26 05:06

Alan


1 Answers

One arguably more elegant solution is to utilize Row Level Security (RLS) to control what data any particular user has access to. While that approach adds some complexity, it's particularly appealing if your API is accessed by users with different roles that have different levels of access. This is actually how postgraphile handles authentication.

You can also potentially use schema directives to keep things DRY and apply some general access logic to a set of individual fields. Apollo's docs actually have an example of doing just that.

Outside of that, yes, your resolvers will need to be context-aware and include logic to limit the data you're exposing.

It's important to point out that these sort of concerns also go back to good schema design in the first place. For example, just because a relationship exists doesn't mean it needs to (or should be) exposed to the client. An order may include one or more products, and if the client needs to display order history, it makes sense to expose a products fields on the Order type. On the other hand, does the client actually need to know all the orders for a given Product?

Similarly, if we have a users field on Order, outside of any user-specific context, such a field would naturally only reflect the users (most likely just the one user) associated with the order. Returning all users as a field on a single order makes no sense. Because of GraphQL's top-down nature, a field is usually going to only be limited to the context of its parent. As a result, it's possible to only have to worry about user context at the root level.

A different, arbitrary example:

query MyOrders {
  orders { # check context for user and limit results to just the logged in user
    user { # user will be based on parent (the order), no need to check context
      orders { # orders will be based on parent (the user), no need to check context  
      }
    }
  }
}

With sound schema design, the resolvers for other types' fields don't necessarily need to do any additional context checking.

like image 133
Daniel Rearden Avatar answered Jun 13 '26 19:06

Daniel Rearden



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!