Hiding Your API Credentials Client Side using a Proxy Server in React

Hiding Your API Credentials Client Side using a Proxy Server in React

·

4 min read

Typically I advise people to use a server-side request to query a GraphQL API. This is because you can hide your API key in the server-side code. However, most Jamstack applications require you to write client-side code, so you can't use a server-side request. When you're in this situation, you can set up a proxy server to reroute your API requests internally, hiding the request from the user. In this post, I'll show you how to hide your API key using a proxy server in React.

Creating a Proxy Server

Suppose you have a React application using Apollo Client to query a GraphQL API, for example, a StepZen GraphQL API. The endpoint requires you to provide an API key as a header, and its implementation in React will look like this:

const client = new ApolloClient({
  uri: 'https://YOUR_USERNAME.stepzen.net/api/YOUR_ENDPOINT/__graphql',
  cache: new InMemoryCache(),
  headers: {
    authorization: `apikey YOUR_API_KEY`,
  },
});

When you use this client in your React application to send requests to the GraphQL API, React will execute the request on the client side. This means that the request is visible from the network tab in the browser, and when you're building an application that external users use they will be able to see this API key.

Luckily, there are ways to prevent this. Either by rendering your React application on the server side or by setting up a proxy server. The library http-proxy-middleware is a great tool to use when you want to proxy requests to an API. It only takes a couple of lines of code to set up and use, and it's very flexible. You can use it to proxy requests to any API, not just StepZen. You can also use it to proxy requests to multiple APIs.

The code block below shows how to use http-proxy-middleware to proxy requests to a StepZen GraphQL API. When you're for example using Create React App (read more here), the proxy server is set up in a file called src/setProxy.js in the root of your React application:

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function (app) {
  app.use(
    '/api/YOUR_ENDPOINT/__graphql',
    createProxyMiddleware({
      target: 'https://YOUR_USERNAME.stepzen.net',
      changeOrigin: true,
      headers: {
        authorization: 'apikey YOUR_API_KEY',
      },
    }),
  );
};

Or, even better, you can use the dotenv package to store your API key in a .env file and use it in your proxy server. This way, you can keep your API key secret without worrying about it being exposed in your code. The package is already installed in the create-react-app template, so you don't need to install or import it yourself.

In an .env file, you can store your API key like this:

`STEPZEN_API_KEY=YOUR_API_KEY`

And use it in src/setupProxy.js:

`authorization: `apikey ${process.ev.STEPZEN_API_KEY}`,`

Now you can run your app locally (with npm start) to make the GraphQL API available at http://localhost:3000/api/YOUR_ENDPOINT/__graphql. When you request this endpoint, or the shorthand api/YOUR_ENDPOINT/__graphql, a request to https://YOUR_USERNAME.stepzen.net/api/YOUR_ENDPOINT/__graphql will be made by the proxy server. The proxy server will also add the authorization header to the request so that it won't be available to the user of your application.

When using Apollo Client, or a different way to make GraphQL requests, you can use the same proxy server to make requests to your StepZen API:

const client = new ApolloClient({
  uri: '/api/YOUR_ENDPOINT/__graphql',
  cache: new InMemoryCache(),
});

This way, you can make requests to your StepZen API without exposing your API key to the user of your application.

Usage with Next.js

This example demonstrated how to use http-proxy-middleware with a Create React App, but there are more examples of integrating a proxy server with other frameworks and libraries. Such as with Next.js, one of the most popular React frameworks.

For Next.js you would implement the proxy server an API Route instead of src/setupProxy.js. This API Route would be named after the GraphQL endpoint you want to target. Suppose you want the proxy to run on http://YOUR_APP_URL/api/YOUR_ENDPOINT/__graphql. Then you would create a file called api/YOUR_ENDPOINT/__graphql.js and add the following code:

import type { NextApiRequest, NextApiResponse } from 'next';
import { createProxyMiddleware } from 'http-proxy-middleware';

const proxyMiddleware = createProxyMiddleware({
  target: 'https://YOUR_USERNAME.stepzen.net',
  changeOrigin: true,
  headers: {
    authorization: 'apikey YOUR_API_KEY',
  }
});

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  proxyMiddleware(req, res, (result: unknown) => {
    if (result instanceof Error) {
      throw result;
    }
  });
}

export const config = {
  api: {
    externalResolver: true,
  },
};

Now you can run your app locally (with npm run dev), and it will use your proxy server to make requests to your StepZen API. Like the Create React App example, you can query the GraphQL API at http://localhost:3000/api/YOUR_ENDPOINT/__graphql (or shorthand /api/YOUR_ENDPOINT/__graphql), and the proxy server will port the request to https://YOUR_USERNAME.stepzen.net/api/YOUR_ENDPOINT/__graphql -- including the authorization header.

What's next?

You can also deploy your app to Netlify or Vercel, and it will use the proxy server to make requests to your StepZen API. With this small proxy server, you no longer have to worry about potentially exposing your StepZen API Key to any of the users of your application. More examples are available in the http-proxy-middleware documentation.

We'd love to hear your feedback on this blog post and StepZen. Questions? Comments? Ping us on Twitter or join our Discord community to get in touch.