You can find code example for this chapter here.
While directives in the schema are great to define access control in a well-documented way, they have a serious limitation: they are all-or-nothing. A user not in a given Cognito group will be always denied access, for example. But when a user should be able to access a field in some cases but not in others, directives fall short. For example, in our example data model, a user can fetch itself through the
Query.user field but not other users.
To implement this, we'll need to write code in the resolvers. This provides a flexible way as the resolver runtime supports arbitrary code. With this approach, it is possible to check the arguments, the source objects, and the caller identity, fetch extra data from a database, and even drop items from the result. We'll see examples for all of these in this chapter.
We'll implement three checks:
Query.user allows returning only the caller user
User.group returns the object only if the caller is in that group
Query.allUsers returns only users in the caller's group
Let's start with the easiest one! By default, the
Query.user field can fetch any user as long as the caller has access to this field. As we've seen in the Entry points chapter, the first of the two legs of security in GraphQL is what objects are accessible from the
Query type. In this case, we want to limit it to the current user.
For this, the resolver needs two pieces of information: the
username argument and the name of the current user. The former is available under the
ctx.args.username while the latter under the