Authentication and Express Middleware with GraphQL
Tags: webdev, programming, javascript, graphql
Published: 2021-01-25 01:42:44

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

We can create a simple GraphQL server with Express. To do this, we need the `express-graphql` and `graphql` packages.

In this article, we’ll look at how to use middleware with Express GraphQL.

### Express Middleware

We can use Express middlewares as usual if we use `express-graphql` to build our GraphQL server with Express.

The `request` object is available as the second argument in any resolver.

For example, if we want to get the hostname of a request in our resolver, we can write:

```
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');

const schema = buildSchema(`
  type Query {
    hostname: String
  }
`);

const loggingMiddleware = (req, res, next) => {
  console.log(req.hostname);
  next();
}

const root = {
  hostname(args, request) {
    return request.hostname;
  }
};

const app = express();
app.use(loggingMiddleware);
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(3000, () => console.log('server started'));
```

In the code above, we created our schema as usual to get the hostname of the app.

Then we added our `loggingMiddleware` to log the hostname. It calls `next` so we can use our `graphqlHTTP` middleware.

Then in our `root` resolver, we added a `hostname` method, which takes the `request` parameter as the second argument, which has the Express request object.

This is where we can return the `hostname` property from `request` so that we can return it in the response.

This means that we can continue to use middleware to handle authentication as we did with REST APIs.

Popular authentication options for Express include Passport, `express-jwt` , and `express-session` .

### Authentication

We can use `jsonwebtoken` in our Express GraphQL server as follows to add authentication via JSON web token.

To do this, we first install `jsonwebtoken` by running:

```
npm i `jsonwebtoken`
```

Then we can include it in our app and then add it to our Express GraphQL server as follows:

```
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
const jwt = require('jsonwebtoken');
const unless = require('express-unless');

const schema = buildSchema(`
  type Query {
    hostname: String
  }
`);

const root = {
  hostname(args, request) {
    return request.hostname;
  }
};

const verifyToken = (req, res, next) => {
  jwt.verify(req.headers.authorization, 'secret', (err, decoded) => {
    if (err){
      return res.send(401);
    }
    next();
  });
}
verifyToken.unless = unless;

const app = express();
app.post('/auth', (req, res) => {
  const token = jwt.sign({ foo: 'bar' }, 'secret');
  res.send(token);
})

app.use(verifyToken.unless({ path: ['/auth'] }));
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(3000, () => console.log('server started'));
```

In the code above, we have the `verifyToken` middleware to verify the token that’s issued by our `auth` route.

In `verifyToken` , we called `jwt.verify` to verify the token that we passed into the `Authorization` header. If we get an error, then we send a 401 response.

Otherwise, we call `next` to proceed to the next middleware our route.

In the `auth` route, we issue our authentication token by calling `jwt.sign` with whatever content we want as the first argument and the token’s secret in the second argument.

Also, we excluded the `verifyToken` middleware from the `auth` route by using the `express-unless` middleware.

We did that by assigning `unless` to `verifyToken.unless` .

Then now when we want to make a request to our GraphQL server via the `/graphql` route, we have to pass in our auth token to the `Authorization` header.

This keeps our GraphQL requests more secure. However, we should have an encrypted secret if we’re going to JSON web tokens in the real world.

### Conclusion

We can use Express middleware for logging, authentication, or whatever we need them for.

To include middleware, we just call the `app.use` method as usual.

We can exclude routes from using the middleware with the `express-unless` package.

To add authentication via JSON web tokens, we can use the `jsonwebtoken` package to add token issuing and verification capabilities to our Express GraphQL server.