What you'll learn
  • prevent unauthorized users from performing sensitive GraphQL API queries and mutations
Can I use this?

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
anchor

The code that we cover in this tutorial can also be found in our GitHub examples repositoryexternal link.

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:

Exposed GraphQL QueriesExposed GraphQL Queries
(click to enlarge)

Even more important, anybody can create new car manufacturers, with the createCarManufacturer GraphQL mutation:

Exposed GraphQL MutationsExposed GraphQL Mutations
(click to enlarge)

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
anchor

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 articleexternal link.

All of the GraphQL resolver functions are located in the api/graphql/src/plugins/scaffolds/carManufacturers/resolversexternal link folder:

apps/api/graphql/src/plugins/scaffolds/carManufacturers

For purposes of this tutorial, let’s open the simplest resolver function, which is the getCarManufacturerexternal link, and add the following lines of code (parts removed for brevity):

apps/api/graphql/src/plugins/scaffolds/carManufacturers/resolvers/CarManufacturersQuery.ts

If you’re curious about the CarManufacturersPermission interface, you can check its definition in api/graphql/src/plugins/scaffolds/carManufacturers/types.tsexternal link 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 Playgroundexternal link, point it to our GraphQL API’s URL, and try executing the following query:

Misplaced GraphQL API URL?

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:

GraphQL Authorization ErrorGraphQL Authorization Error
(click to enlarge)

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:

Create a Test UserCreate a Test User
(click to enlarge)

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:

GraphQL Authorization SuccessGraphQL Authorization Success
(click to enlarge)

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
anchor

Before we wrap this up, note that this is just a single resolver we secured, and that you should implement the same logic into othersexternal link 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 (DRYexternal link) and our code will be easier to maintain.

FAQ
anchor

I'm Not Building a Multi-Locale Admin Area Application Module.
anchor

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.