Learn how to implement permissions in GraphQL using three different methods: directives, middleware resolvers, and the GraphQL shield library.

Introduction

GraphQL has become the new normal for developing APIs. It has its own advantages and flexibility. One such advantage is that it allows you to implement permissions and granular access control in the API.

Getting granular access control is a big pain in large REST APIs. In GraphQL, you can achieve granularity quite easily.

In this article, we will see different patterns to implement permissions in a GraphQL API.

Basics of access control and permissions

Access control – Checking whether the user is authorized to access the API.

Usually if a user is not logged in but the API endpoint requires a logged in user, the API throws an authentication error.

If the user is logged in but doesn’t have enough permission to perform the operation, the API will throw a forbidden error or an unauthorized error.

Permissions – Permissions is a set of rules that help to make the decision as to whether the user will get access to a particular API.

Let’s check some example use cases for permissions.

Consider the Twitter app:

  • A user can write a Tweet
  • The author who wrote the tweet can delete it
  • Other users can like, retweet, or share the Tweet
  • Other users can report a Tweet
  • Both the author of the Tweet and other users can participate in the comment thread on the Tweet

As you can see, both the author and other users have different levels of permissions, even though the level of authorization is same. They are all authorized as users, but based on activity, they have different rights of access.

Permissions in GraphQL

You can implement permissions in different ways in a GraphQL API. For instance, you can implement permissions through GraphQL directives in the schema or by checking permissions in GraphQL middleware (such as resolvers).

Depth of permissions

In GraphQL, you can go to any depth to implement permissions.

You can do query level permissions, object level permissions, and field level permissions.

Different ways to implement permissions in GraphQL

There are different techniques to implement these permissions: directives, middleware resolvers, and the GraphQL shield library.

We will see all these techniques in our example. Now, let’s build a simple GraphQL server example.

Building a simple GraphQL API

First, create a new npm project:

npm init

Add your express, apollo-server-express and graphql package.

npm i express apollo-server-express

Next, create an index.js file with the sample GraphQL server:

const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');

// Construct a schema, using GraphQL schema language
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// Provide resolver functions for your schema fields
const resolvers = {
  Query: {
    hello: () => 'Hello world!',
  },
};

const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(` Server ready at http://localhost:4000${server.graphqlPath}`)
);

Let’s add nodemon to run the server locally. Nodemon helps to reload the server by watching the files for changes during development:

npm i -D nodemon

Add scripts to run the server in the package.json file:

"scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
},

Let’s start the server in the terminal:

npm run dev

The server will open at the port 4000.

Let’s create few more files and split the code. We’ll use a schema.js file for the GraphQL type definitions:

// schema.js

const { gql } = require("apollo-server-express");
// Construct a schema, using GraphQL schema language
module.exports = gql`
  type Query {
    hello: String
  }
`;

And resolver.js file for the resolvers:

// schema.js

const { gql } = require("apollo-server-express");
// Construct a schema, using GraphQL schema language
module.exports = gql`
  type Query {
    hello: String
  }
`;

Let’s create some data and corresponding queries and resolvers for a simple Tweet application.

The data.js file will be:

// data.js

module.exports = [
  {
    id: 0,
    content: "HTML is a programming language",
    author: "Param",
  },
  {
    id: 1,
    content: "JavaScript programmers are beginners",
    author: "Param",
  },
  {
    id: 2,
    content: "HTML and CSS pages are enough to build a bank project",
    author: "Joshua",
  },
  {
    id: 3,
    content: "React Js can prove earth as flat in 2025",
    author: "Joshua",
  },
];

Now, we will create queries and resolvers to display this Tweet data:

// schema.js

const { gql } = require("apollo-server-express");
// Construct a schema, using GraphQL schema language
module.exports = gql`
  type Query {
    hello: String
    tweets: [Tweet]!
    tweet(id: Int!): Tweet!
  }

  type Tweet {
    id: Int!
    content: String!
    author: String!
  }
`;

Resolvers for the tweets and tweet query:

// resolvers.js

const { ApolloError } = require("apollo-server-express");
const tweets = require("./data");

// Provide resolver functions for your schema fields
module.exports = {
  Query: {
    hello: () => "Hello world!",
    tweets: () => {
      return tweets;
    },
    tweet: (_, { id }) => {
      const tweetId = tweets.findIndex((tweet) => tweet.id === id);
      if (tweetId === -1) return new ApolloError("Tweet not found");
      return tweets[tweetId];
    },
  },
};

We now have the basic GraphQL server ready. Let’s jump into the graphQL permissions through examples.

#graphql #api #database #web-development #developer

3 Ways to Implement Permissions in GraphQL API
2.75 GEEK