How is everyone doing authentication across relations to prevent data from being traversed via relations?
For example we have a Shop which has Users.
// Returns error as i've set custom resolver to allow only context.user.is_shop_owner
{
shops {
name
users {
email
...
}
}
}
This query is normally blocked with a custom resolver like context.user.is_shop_owner
, so you cannot execute this from root query.
However, if a malicious person traverses relations to reach the users object he is able to get the sensitive user data.
// Data exposed un-intendedly due to relation traversal. How to prevent this?
{
products {
name
price
shop {
users { ... } // boom, exposed
}
}
}
Is this a flaw in graphql? How are you guys working around this?
This is on a python-graphene stack btw.
Edit: Btw, i know we can do exclude_fields
, but then i won't be able to access Users from the ShopNode, which is an important information to query for the ShopNode, so limiting fields are probably not a good idea. (edited)
I wound up setting custom resolvers for each node to block out the relations you want to limit access to based on the context.user
. Refer to the code below in response to my question above.
class ProductNode(DjangoObjectType):
class Meta:
model = Product
interfaces = (graphene.relay.Node)
# Exclude nodes where you do not need any access at all
exclude_fields = ['users']
# For nodes where you need specific/limited access, define custom resolvers.
# This prevents the relation traversal loophole
def resolve_shop(self, args, context, info):
""" Allow access to nodes only for staff or shop owner and manager """
if get_is_staff_user(context.user, self):
return self.shop
Operations.raise_forbidden_access_error()