Admin Area > New App Tutorial
Securing GraphQL API
Learn how you can secure your GraphQL API.
- prevent unauthorized users from performing sensitive GraphQL API queries and mutations
In order to follow this tutorial, you must use Webiny version 5.9.0 or greater.
Learn more about the Webiny Security Framework in the Security Framework key topics section.
Overview
The code that we cover in this tutorial can also be found in our GitHub examples repository.
At the moment, all car manufacturers-related queries and mutations that we’ve added to our GraphQL API are publicly exposed.
For example, if were to perform a simple listCarManufacturers
GraphQL query, we would receive a list of all car manufacturers:
Even more important, anybody can create new car manufacturers, with the createCarManufacturer
GraphQL mutation:
In most cases, this is not the desirable behavior, and you’ll certainly want to have control over who can perform these GraphQL operations, and who cannot.
Securing GraphQL API Resolvers
In order to secure the car manufacturers-related GraphQL API queries and mutations, we have to revisit the GraphQL resolver functions that were generated for us via the Extend Admin Area scaffold.
Learn more about GraphQL resolver functions in the official GraphQL documentation article.
All of the GraphQL resolver functions are located in the api/code/graphql/src/plugins/scaffolds/carManufacturers/resolvers
folder:
For purposes of this tutorial, let’s open the simplest resolver function, which is the getCarManufacturer
, and add the following lines of code (parts removed for brevity):
If you’re curious about the CarManufacturersPermission
interface, you can check its definition in api/code/graphql/src/plugins/scaffolds/carManufacturers/types.ts
file.
In order to actually compile the code changes we’re about to make and see them in our GraphQL API, we need to run the following Webiny CLI command:
To learn more, check out the Use the Watch Command guide.
Now, to see this new piece of authorization logic in action, we can use a GraphQL client, for example the GraphQL Playground, point it to our GraphQL API’s URL, and try executing the following query:
Running the yarn webiny info
command in your Webiny project folder will give you all of the relevant project URLs, including the URL of your GraphQL API.
Without including the appropriate Authorization
request header, we should receive the following error response:
If you’ve received the Not authorized. error, that means authorization was successful.
On the other hand, if a valid Authorization
request header is included, or in other words, the current identity actually has access to the Car Manufacturers module, the data should be returned.
To manually test that, we can simply create a new user via the Webiny Security application, and either place it into the default Full Access security group, or even better, into the newly created Car Manufacturers security group. Which is what the following screenshot is showing:
Once we’ve created the user, we can log in into the Admin Area application with it (using its username and password), and execute the same GraphQL query, this time using the built-in API Playground. We will use this client simply because of the fact that, upon issuing GraphQL operations, it will automatically attach the correct Authorization
request header for us. In other words, it will perform GraphQL operations as the currently logged-in user.
Learn more about the API Playground GraphQL client in the API Playground guide.
So, as we can see in the following screenshot, the GraphQL query was successful, as we’ve successfully received the car manufacturer data in the response:
This means that the user we’re currently logged-in with has the appropriate security permissions, and that the newly added authorization code works as expected.
Final Notes
Before we wrap this up, note that this is just a single resolver we secured, and that you should implement the same logic into others as well.
Also, in case you start seeing yourself copying some of the authorization related code, it’s certainly recommended that you extract it into one or more separate utility functions. This way we’re not repeating our selves (DRY) and our code will be easier to maintain.
FAQ
I'm Not Building a Multi-Locale Admin Area Application Module.
If you’re not building a multi-locale Admin Area application module, feel free to skip the await context.i18nContent.hasI18NContentPermission();
checks in your GraphQL resolvers and simply start with your own authorization checks.
But of course, be aware that if your project ends up being multi-locale, then users will be able to execute GraphQL operations in every created locale. At that point, you will most probably want to bring back the removed locale-related authorization checks.