This approach can be likened to an API Gateway as the core concept here is that people can only access resources that they are authorized to, and unauthorized access is blocked off in the API itself.
Clear separation of authorization logic from business logic.
It makes sense to implement authorization in Business Logic Layer below the API/GraphQL layer as that would allow you to use the same authorization logic for access methods other than API. However this approach makes it difficult to allow the accessors/client to determine what they have access to, and many times the only way for a client to do so is by hitting an end point and then observing the respons.
In the API/GraphQL layer of execution we perform the following operations:
Modify the schema by applying the authorization mask.
Business logic and other services can implement or not their own authorization, as main authorization can be controlled by teams responsible for security.
While implementing, the following factors should be considered.
We should apply an authorization mask and cache the schema associated with that mask and on subsequent requests associated with the mask simply fetch the schema removing any performance degradation caused by masking logic.
As an additional benefit, nodes that are not authorized will not be executed as the request executor will not invoke the requests since they will not appear on the schema. This would improve the performance by minimizing execution compared to implementations in which the requests need to be executed until the business logic layer responds with errors regarding unauthorized access.
While the authorization mask is generated we might disable certain nodes which would break the schema as we might have orphan edges on different nodes pointing to the node which has been masked out.
This can be addressed by providing mask generators with a schema validation check and subsequently masking out the orphan edges.
As a client might develop an application thinking of the entire schema being available, while their users may have limited access and receive incomplete responses.
This can be addressed by checking for null responses on the client as is the standard and from the server responding with an unauthorized access error message if needed.
We will now be hitting unauthorized requests in 2 cases,
We can look at the problem generally as trying to distinguish a maliciously crafted request accessing deprecated nodes vs an old client accessing deprecated nodes. This problem needs to be addressed on a case-by-case basis in forensics stage where a certain amount of contextual data, not necessarily related to GraphQL's request itself will be key in differentiating between the two. As it stands, we do not have a solution to this problem.