Frontend Serverless with React and GraphQL

Start at the beginning and work your way through this project. The code for each step as well as the finished project can be found in the Github repository.


41. Lock down the GraphCMS Api

Objective: Lock down the api by requiring an api key to make requests to GraphCMS.

In the last step we added a api route that makes requests for us to GraphCMS based on requests made from the frontend. We haven't added any sort of protection to block users from making requests directly to GraphCMS and thus bypassing this api endpoint that we just created so let's do this now.

Steps to require token authorization on the GraphCMS backend:

  1. Click on settings then the API Access panel in your GraphCMS project.
  2. Create a permanent auth token by first giving it a token name. It can be whatever name you want.
  3. Select the "content from stage draft" checkbox.
  4. Select the enable mutations button.
  5. Press create and you'll see a new token get added under the existing token section below.
  6. Press the copy button.
  7. Open up your .env file and add a new variable called GRAPHCMS_TOKEN and set it equal to this copied token.

.env

//other tokens above
GRAPHCMS_TOKEN=your-very-long-token-here
  1. While we are defining envs let's also add this as a new secret to Vercel as well.

Now that we have our token, we need to add the environmental variable to the next.config.js file. Make sure that it is in the serverRuntimeConfig block so that it never gets exposed to the frontend. If it did get exposed we would have to create a new token and delete the existing one because it could allow someone to take the token, bring it into their own app and make any requests they want against your own backend! Not a good look.

next.config.js

require('dotenv').config();
const {
BRANCH,
GRAPHCMSURL,
GRAPHCMSPROJECTID,
domain,
clientId,
clientSecret,
scope,
redirectUri,
postLogoutRedirectUri,
cookieSecret,
BACKEND_URL,
GRAPHCMS_TOKEN,
} = process.env;
module.exports = {
publicRuntimeConfig: {
backend: { BACKEND_URL },
},
serverRuntimeConfig: {
graphcms: {
BRANCH,
GRAPHCMSURL,
GRAPHCMSPROJECTID,
GRAPHCMS_TOKEN,
},
auth: {
domain,
clientId,
clientSecret,
scope,
redirectUri,
postLogoutRedirectUri,
},
cookieSecret,
},
};

Next you will have to restart your server since you changed the next.config.js file. Once you are back, we will need to edit the graphql proxy file. The typical way that you authorize a request is by adding an authorization header. This is a header that we will add on our request from our graphql api function to the GraphCMS backend.

pages/api/graphql.ts

import getConfig from 'next/config';
import { GraphQLClient } from 'graphql-request';
const { serverRuntimeConfig } = getConfig();
const {
BRANCH,
GRAPHCMSURL,
GRAPHCMSPROJECTID,
GRAPHCMS_TOKEN,
} = serverRuntimeConfig.graphcms;
const graphqlEndpoint = `${GRAPHCMSURL}/${GRAPHCMSPROJECTID}/${BRANCH}`;
export const graphQLClient = new GraphQLClient(graphqlEndpoint, {
headers: {
authorization: `Bearer ${GRAPHCMS_TOKEN}`,
},
});
async function proxyGraphql(req, res) {
try {
const { variables, query } = req.body;
const data = await graphQLClient.rawRequest(query, variables);
res.json(data);
} catch (e) {
res.json({ data: {}, errors: [{ message: e.message }] });
}
}
export default proxyGraphql;

Once you've added this try to go to the home, my recipes, and favorites page to confirm that they all still properly load. Now that we have locked down our backend, it is time to start blocking certain types of requests so that we have more control over what we will allow users to do.