Steps to Building Authentication and Authorization For GraphQL APIs
Tags: api, graphql
Published: 2019-05-15 10:49:47

---
title: Steps to Building Authentication and Authorization For GraphQL APIs
published: true
description: How to authenticate users and check their permissions in a GraphQL API
canonical_url: https://www.moesif.com/blog/technical/api-design/Steps-to-Building-Authentication-and-Authorization-For-GraphQL-APIs/
tags: api, graphql
cover_image: https://thepracticaldev.s3.amazonaws.com/i/s1jmfvfm6exnb8edxe84.jpg
---
When building an API, it's often a bad idea to serve all data to everyone on the Internet. For business reasons we need to check, who is a paying customer and for security and privacy reasons we need to restrict access to parts of our system.

We've already written [an article about authentication and authorization with REST APIs](https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/).

In this article, we will dive into the auth topic with GraphQL.

## The Difference Between Authentication and Authorization

Both are often lumped together with the word _Auth_ as in _"We need to add auth capabilities to our system."_

While the two topics are intertwined, they cover different aspects.

Authentication is about knowing **who** wants to do something with our system.

We can solve this problem with a login via username/email and password or social logins with GitHub or Facebook etc.

Authorization is about knowing **what** they are allowed to do with our system.

This problem is more involved in that it deeply dependent on our business cases. While it isn't apparent, authorization is business logic and should be treated as such.

## Authentication, Authorization, and GraphQL

Where do we place this logic in our GraphQL APIs?

[The opinion of the GraphQL creators](https://graphql.org/learn/authorization/) is to _"delegate authorization logic to the business logic layer"_. They don't have any strong opinion on authentication besides the fact that creating _"fully hydrated user-objects"_ instead of passing auth-tokens down to our business logic.

What does this mean? Where is our business logic located? Where would we create these user-objects?

### Structure of a GraphQL System

A GraphQL system could be structured as seen in the following picture:

<img src="https://thepracticaldev.s3.amazonaws.com/i/75tvovigykdkogeq519s.png" alt="GraphQL System Structure" width="500">

On the left, we have different types of _middleware_ that apply some logic to all of our requests.

In the middle we have the _GraphQL engine_, that figures out how to translate our GraphQL queries into calls to the right resolver functions with the help of our GraphQL Schema. In most frameworks, like the Express framework for Node.js, the GraphQL Engine is also implemented as middleware.

On the right, we have different types of _resolver functions_ that connect the GraphQL engine to our business logic. A resolver gets executed by the GraphQL engine when its corresponding data type was queried.

The business logic could be one monolithic system or a bunch of microservices.

### Integration of Authentication into GraphQL

To _authorize_ a request, we need access to the current users' identity in our business logic. This requires us to put the _authentication_ logic into a place that gets executed for all our requests. If we look at the graphic above, this makes the middleware-part of our system the perfect place for it.

Another nice thing of this approach: It's completely independent of GraphQL, so we can re-use our REST skills and re-apply them!

If you need to freshen-up your REST authentication skills, [read our previous article](https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/#).

### Integration of Authorization into GraphQL

To get a sense of this, let's look at a simple implementation of middleware, a REST resource handler function, and a GraphQL resolver function. For this example I will use Node.js with the Express framework and the Apollo Server.

First, our business logic:

```javascript
const getMessage = (id, user) => {
  const message = dataStore[id];

  if (message.recipient.id === user.id) return message;

  if (message.sender.id === user.id) return message;

  throw new Error("no permission");
};
```

It loads a message by ID from in-memory storage. If the user is the recipient or the sender of this message, they're allowed to read it. Otherwise, we throw an error.

Second, the authentication middleware:

```javascript
const authMiddleware = (request, response, next) => {
  const token = request.get("authorization");
  const user = loadUser(token);
  if (user) {
    request.user = user;
    next();
  }
  response.status(401).end();
};
```

It loads a token from a request header and uses it to load the current user. If that worked, it adds this user-object to the request so that it can be used later.

Now, let's look at the REST implementation.

```javascript
expressApp.use(authMiddleware);

expressApp.get("/message/:id", (request, response) => {
  try {
    const message = getMessage(request.params.id, request.user);
    response.end(message);
  } catch (e) {
    response.status(403).end({ error: e.message });
  }
});
```

First, we use our `authMiddleware`; this makes sure that our `request` has a `user` object in our endpoint handlers.

Then, we define a function that is called for a GET request to our `/messages/:id` endpoint. It uses the `id` parameter and the `user` object of our `request` to load a `message` with our _business logic_ function.

When everything went right, we get the `message` and can send it to the client. If not, we set the HTTP status to `403` (forbidden).

The `getMessage` function handles the authorization with the help of the `user` object. It doesn't care where it comes from.

Next, let us look at a GraphQL implementation, here created with [Apollo Server](https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-express).

```javascript
expressApp.use(authMiddleware);

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

const typeDefs = gql`
  type Query {
    message(id: String!): String
  }
`;

const resolvers = {
  Query: {
    message: (parent, args, request, info) =>
      getMessage(args.id, request.user)
  }
};

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

The use of the middleware stays the same here. So no changes needed for authentication.

We then use the `apollo-server-express` module to define a simple GraphQL API that only has a `Query` type with a `message`.

Then we define our resolver function, which looks almost the same as in the REST example.

Resolvers get four arguments, the third being the `request` we already know from our REST implementation. Since our middleware used this object to attach the `user` object, we can pass it on to our business logic as we did before.

The GraphQL engine parsed the `id` parameter from our query and stored it into the second parameter, so only its location is different.

Our business logic function handles the authorization, the same as in the REST implementation.

The difference here is that **GraphQL doesn't know about HTTP** or its status codes. If it can process a query (even with empty results), it will just use `200`.

The error thrown by our business logic will be placed inside an `errors` array in the response body and can be handled there in some way by the client.

The `message` of our response JSON will be set to `null`, this allows us to respond with partial data to the clients' requests. For example if the message would have been somewhere deep in the GraphQL response tree.

```json
{
  "data": {
    "message": null
  },
  "errors": [
    {
      "message": "no permission",
      ...
    }
  ]
}
```

> _What is Moesif? [Moesif](https://www.moesif.com/features/graphql-analytics) is the most advanced REST and GraphQL analytics platform used by over 2000 organizations to measure how your queries are performing and understand what your most loyal customers are doing with your APIs._

## Handling in the Client

Now that we have talked about authentication and authorization in our API, we should also look at the client side of things.

### Client Authentication

If we go for token-based authentication, which is currently the most prominent, we first need to acquire such a token. We can do this in two ways.

**Auth Token Retrieval**

1. We create extra HTTP endpoints for signup and sign in
2. We create GraphQL mutations for signup and sign in

Extra HTTP endpoints decouple the whole process of authentication from the GraphQL API. Like the middleware approach on the server-side did. This is especially nice if the service that does authentication is different from our API and we only need a token from it.

GraphQL mutations feel more integrated but require more special cases in our API, because we need to let users access them somehow without being authenticated.

In my opinion, the first way is less risky. We can focus on our core-competencies in our GraphQL API and stay flexible for the future.

**Token Storage and Placement**

The token needs to be sent to our API alongside with our GraphQL requests.

For this, we need to decide where to store the token and where on a request to place it.

There are two ways for storage, [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) and [HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies).

When storing in `localStorage`, we can send the token via HTTP headers. When we store it in cookies, we send it automatically with the cookies.

It's the same as with REST APIs, and both variants have their pros and cons. I won't go into detail, but you can read about it in our [REST auth article](https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/#the-real-debate-cookie-vs-local-storage).

**Example with Apollo Client**

Let's look at a simple example with Apollo Client, a UI-framework independent GraphQL client library written in JavaScript.

```javascript
import { ApolloClient } from "apollo-client";
import { HttpLink } from "apollo-link-http";
import { ApolloLink, concat } from "apollo-link";

const httpLink = new HttpLink({ uri: "/graphql" });

const authMiddleware = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      authorization: localStorage.getItem("token") || null
    }
  });

  return forward(operation);
});

const client = new ApolloClient({
  link: concat(authMiddleware, httpLink)
});
```

[Source: Apollo Client Docs](https://www.apollographql.com/docs/react/advanced/network-layer)

Here we use the `localStorage`/header variant to store and send the token.

Apollo client has a network layer called _Apollo Link_. This is used to make different protocols pluggable. A **link** is implemented as middleware, as we saw in the back-end in our Express examples.

In this example, we configure the HTTP middleware to our GraphQL API endpoint and then create a custom middleware/link for authentication.

Both get plugged into the `ApolloClient` constructor, so they get executed for all GraphQL queries we send.

The custom `authMiddleware` looks into `localStorage` before every request and sets the `authorization` HTTP header to the token it found.

Here we already see the pros of keeping the authentication out of GraphQL. We can do a simple `fetch` call to an HTTP endpoint for signup or sign in and store the received token somewhere before we even start creating our GraphQL client objects.

This also works the other way around. If we want to sign out a user, we can throw away the GraphQL client object, without any need to mutate it in some way.

### Client Authorization

If we set up the authentication correctly, the API now knows that we are who we say, but there is still the possibility that we want to query for data we aren't allowed to access.

On the client, like on the back-end, authorization is business logic, so we need to think about what to do in specific cases.

We have a UI, send one big GraphQL query to get all the data in one swoop, and now it comes back with some fields being `null` and a few errors.

The **Apollo Client** library defines [three error policies](https://www.apollographql.com/docs/react/features/error-handling) for this, and we can set one of them for every or all request.

These policies define behavior which we can also use in custom clients or when we `fetch` directly without any particular GraphQL library.

1. If any GraphQL error is present in the response, we consider it failed, and we throw it away, like when a network error occurred.
2. We ignore all errors in the response and try to use the data as is.
3. We try to use the GraphQL errors inside the response in tandem with the data that was returned to show the user the best we can and display the errors alongside so they know why some parts are missing.

## Conclusion

Authentication and authorization are very important topics in API design, but as this article showed, once we understand the basics of authentication for HTTP APIs, we can reuse our skills on REST and GraphQL without much change.

It's also important to understand that authorization is business logic and often completely customized for a specific software product. This means it should be pushed to the edges of our code-base, so it can be found easily and doesn't repeat itself in many places.

---

*Moesif is the most advanced GraphQL Analytics platform. Over 2000 organizations use Moesif to track what their most loyal customers do with their APIs.* **[Learn More](https://moesif.com/features/graphql-analytics?int_source=dev.to)**

---

Originally published at www.moesif.com