AWS AppSync, GraphQL and Authorisation
Currently I’m working on a business idea using AppSync specifically GraphQL. GraphQL seems to become the next REST API. For people who have no idea what a REST API is. The REST API is an approach which allows internet services to exchange data. If you are using a website, the probability that this website is accessing data or content using such an API. Social media services like Hootsuite are using REST APIs to access Twitter data, as well.
GraphQL is an industry standard supported and mainted by the GraphQL foundation (https://foundation.graphql.org). With members like Amazon AWS, IBM, AirBnB and others.
Why is GraphQL supposed to be better than REST API?
REST API is not a technology as such, it is a set of principles, which basically formulates how resources should be accessed via the Internet (frontend and backend wise).
GraphQL is a formalised standard, and standard solutions. GraphQL for example is type oriented (lack of type safety is a common software quality problem).
REST API does not know or defines how you have to implement your resources, this is giving you a lot of freedoms but it also allows for many errors and costly mistakes. Further it is doubtful that a great degree of freedom implementing your REST API resources is giving you a competitive advantage.
GraphQL on the other hand is standardising the way how to organize your backend resources. How to specify reads and writes for example. A GraphQL service (like for example AWS AppSync) is behaving like a database. Instead of directly addressing resources like with an REST API, you query the data. Hence the name Graph Query Language.
From that perspective GraphQL can be considered to be a standard comparable to SQL (Structured Query Language, very common way how to query databases).
Authorisation and Ownership
In the naive world of software developer examples there are no ownerships, all data belong to all developers. Within the nastiness of reality this unfortunately not the case.
Which means we need to specify which data belongs to whom. That’s called the ownership.
AWS is offering a broad range of different authorisation methods and approaches out of the box, also for AWS AppSync. Unfortunately these methods don’t manage data ownership. You have to do this on your own.
I was looking into my app and its GraphQL, and in this case how to access data using an API Key (API Keys are a common method to access data for backend services, another one are service accounts).
It’s all well, you can create API Keys, you can authorise general access to data, you can do this even on a field level, but nowhere there is a standard to restrict data access depending based on ownership.
Frontend Bias
The available documentation is also rather sparse here, and even leaves the impression that API Keys are evil and should only be used for development.
The reason is, that for some reason either google search algorithms and/or AWS itself are putting frontend related documentation in the foreground. Which could leave the impression that GraphQL is for the frontend only (iOS, Android, JavaScript). Which would render the argument that GraphQL is the next REST API invalid.
Solution for API Keys and Ownership
The solution for API Keys and ownerships is to map the API Key to user related data (in you Auth provider or a table). In my case I will map the API Key to the user, by putting the API Key as a search index in the dynamo table of the user master data.
To make it work, I also need to fetch the API Key from incoming requests, for Lambda events it is the field x-api-key which can be read from the event (event->request->headers->x-api-key).
The x-api-key is used to resolve the userId and the userId is used as a parameter to filter the data or if data are created.
I’m using Lambda functions for the resolvers which are called by AWS AppSync and you can put any business logic into them (but be aware about runtime).
Summary & Preconditions
To make it work you need:
- GraphQL Schema: type, queries, mutations do need @aws_api_key keyword (and probably also @aws_cognito_user_pools)
- The GraphQL API needs API Key as authorisation method (can be added manually using the GraphQL console, should be added using your build pipeline) https://docs.aws.amazon.com/cdk/api/latest/docs/aws-appsync-readme.html
- An API Key created for this GraphQL API (API Keys <-> API Id), for example using: “aws appsync create-api-key — api-id xxx”
- Kind of a client to access your API for testing https://sammart.in/post/2020-05-17-querying-appsync-with-python/
- Lambda functions which are aware that they need to map the API Key to an owner / user https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html, https://medium.com/@bishonbopanna/appsync-how-to-allow-guest-access-while-limiting-authenticated-users-access-to-only-what-they-bfbb5b0c5706