Protect GraphQL APIs with Unkey

16 Oct 2023

In this tutorial, we'll learn how to use the GraphQL Yoga Plugin system to protect requests using API keys with Unkey.

Prerequisites

Let's begin with a very simple GraphQL schema and server:

import { createSchema } from "graphql-yoga";

const schema = createSchema({
  typeDefs: /* GraphQL */ `
    type Query {
      hello: String
    }
  `,
  resolvers: {
    Query: {
      hello: () => "world",
    },
  },
});
import { createServer } from "node:http";
import { createYoga, createSchema } from "graphql-yoga";

const yoga = createYoga({
  schema,
  plugins: [],
});

const server = createServer(yoga);

server.listen(4000, () => {
  console.info("Server is running on http://localhost:4000/graphql");
});

To get things started, we'll run the server locally using ts-node:

npx ts-node server.ts

Sign up to Unkey

Go to Unkey.dev, signup and create a new API project.

Create a custom Yoga plugin for Unkey

Since we'll be veriying API keys only, we can use the @unkey/api dependency to verify the API key. Let's install it:

npm install @unkey/api

Now add the following imports to the server.ts file:

import { createYoga, createGraphQLError, type Plugin } from "graphql-yoga";
import { verifyKey } from "@unkey/api";

We'll be hooking into the onRequestParse plugin hook to verify the API key. Let's create a plugin that does that:

function useUnkey(): Plugin {
  return {
    async onRequestParse({ request }) {
      const token = request.headers.get("x-unkey-api-key") as string;

      if (!token) {
        throw createGraphQLError("No API Key provided");
      }

      // ... verify the API key

      // ... throw if an error

      /// ... throw if the API key is invalid
    },
  };
}

Verify the API key

Let's add the following code to the onRequestParse plugin hook to verify the API key using the @unkey/api dependency:

function useUnkey(): Plugin {
  return {
    async onRequestParse({ request }) {
      const token = request.headers.get("x-unkey-api-key") as string;

      if (!token) {
        throw createGraphQLError("No API Key provided");
      }

      const { result, error } = await verifyKey(token);

      if (error) {
        throw createGraphQLError(error.message);
      }

      if (!result.valid) {
        throw createGraphQLError("API Key is not valid for this request");
      }
    },
  };
}

That's it! We've successfully created a custom Yoga plugin that verifies the API key using Unkey for each request.

Add the plugin to the Yoga server

Now invoke useUnkey() inside the plugins array:

const yoga = createYoga({ schema, plugins: [useUnkey()] });

Test the API

Before we can test the API you will need to generate an API key for each individual user. For the purposes of this tutorial, we'll do that manually using the Unkey Dashboard.

Once we have the API key we can pass the header x-unkey-api-key to the request.