Hide your API key: Part 1 - Intro

Photo by FLY:D on Unsplash

Hide your API key: Part 1 - Intro

The tip of the back-end iceberg

This is the first article in a series to help other beginners learn how to hide the API keys for their front-end projects. This part will just lay out the issues, and the high level solution. The next few will walk you through the actual process start to finish.

If you are totally new to JavaScript, this series might not be for you. You will need to understand or at least be familiar with async, functions, object destructuring, fetch, import/export, and other intermediate concepts. You should also know command line/terminal basics, basic Git concepts, and the basics of NPM.

Ask yourself the following

Have you built a simple app? Does it fetch data using an API and a key? Did you know you should hide the API key?

Yes, yes, and yes?

Did you know that there is no real way to hide an API key in front-end code?

You cannot hide an API key without back-end code

If for example you save the API key to an external object, then import the object for use in a function using fetch to make an API call, your API key is still not hidden. It will show up in the Network tab of the developer tools when you make a call to the API.

Of course, if you commit a file with the key in it, the whole world can now see it.

Most of that is common knowledge to most JavaScript learners, but from what I have seen, a lot of the front-end tutorials and courses do a great job of teaching front-end, API manipulation, React, etc., but a very poor job at teaching the basic things necessary to hide the API key you were just instructed to set up--and protect.

This is where Netlify comes in. Specifically, Netlify functions.

What is a Netlify function?

A Netlify function can be many things. In the context of this article however, it allows you to have others (read: potential employers) actually use your app while hiding the API key (while still having a functional fetch).

In a nutshell, a Netlify function serves as the backend, without the need to pay for an actual server.

For example, below is the relevant excerpts of very basic Netlify function. It makes an API call to the TMDB API.

// search.js - Netlify function, runs in Node
async function handler(event) { // The "event" parameter is important
    const TOKEN = process.env.TOKEN; // Take note
    const { query: searchTerm } = event.queryStringParameters;
    // "query" from the front-end function is passed to this function

    const endpoint = "https://api.themoviedb.org/3/search/movie";
    const URL = `${endpoint}?query=${searchTerm}`;
    const options = {
        method: "GET",
        headers: {
              accept: "application/json",
              Authorization: `Bearer ${TOKEN}`,
        },
    };

    const response = await fetch(URL, options);
    const data = await response.json();

    // Try/catch should be used here, but this is just a
    // basic example
    return {
        statusCode: response.status,
        body: JSON.stringify(data),
    };
}

module.exports = { handler };

The Netlify function (saved as search.js) should be paired with the below front-end function (in this case, also written as part of a larger React app).

This function runs in the browser.

// Front-end function - Browser
async function getSearchResults() {
    const { searchTerm } = appState; // React stuff

    const netlify = `/.netlify/functions`; // Magic begins here
    const URL = `${netlify}/search?query=${searchTerm}`;
    // "search" pairs with the filename of the Netlify function above
    // "query" is the URL parameter used in the Netlify function

    const response = await fetch(URL);
    const data = await response.json();
    const { results } = data; // Destructure "results"

    setAppState((prev) => ({
        ...prev,
        searchResults: results,
    }));
}

Plain English

The front-end function will not directly access the API. Instead, the front-end function will go through the Netlify function to access the API. To do so, the front-end function will pass the query URL parameter to the Netlify function.

Simultaneously, the Netlify function will securely access the API key. The API key itself (i.e. TOKEN) is written in either (a) an .env file stored on your computer (for developing the app and testing it locally) or (b) on Netlify itself (for your published app).

With the API key in hand, the Netlify function will then use the query URL parameter passed to it, accessed by the event function parameter. event is an Object, with a queryStringParameters key, itself with a value that is also an Object.

The keys in queryStringParameters are--you guessed it--the URL parameters from getSearchResults (technically defined in const URL = `${netlify}/search?query=${searchTerm}` ).

// Schema
event = {
    queryStringParameters: {
        query: "",
        // others ...
    },
    // ...
}

Step-by-step

  1. The end user inputs information

  2. The front-end function passes information to Netlify function

  3. The Netlify function accesses that information

  4. The Netlify function securely accesses the API key

  5. The Netlify function makes a call to the API using the passed information

  6. The API returns data

  7. The Netlify function makes that data accessible to the front-end function

  8. The front-end function displays the data on the page (or in the console)

Now that we understand what is happening conceptually, in Part 2 we will start to learn how to set all of this up, from scratch, on our own computers.

I do not have a target date for Part 2!