This is a tutorial from my digital portfolio/blog. Please stop by and take a look, then criticize me in the comments. Haha.
Many of you are reading this because you are an awesome Front-End Developer with a sick idea, but don’t quite know how to secure some of the necessary API calls without a full back-end environment. You hop online and everyone is telling you to put your API keys in an .env file then blah blah blah and rest easy. Well, if you have sensitive API keys and you follow the .env advice, you are putting yourself at a high risk.
Here is why a .env file doesn’t protect you in production:
The background is that when React creates the production build, it jumbles everything up into a chunk.js file. If you have a react project with some API keys, do me a favor and go to the page, then inspect it using the DEV tools. Go to Sources, then go to the static folder, then go to the js folder. There is a weird filename that you probably don’t recognize that ends with chunk.js. Open that file up and copy the contents to a word processor (I tried searching in the inspect tool, but it was suuuuper slow). Go to your sacred .env file and copy one of your “secure” API keys, then jump back into your word processor. Try a find on your API key. What is that you say, your key is in this PUBLIC file?
Well, you have some work ahead of you, but fret not, you can use Google Firebase to act as a back-end server and save your back-end from API fraud and ending up like this guy. I’ll line out how I did it and if I can do it, you should be able to. You do need to be on the Blaze plan for this to work. If you make a lot of external API calls in a month, you could end up paying.
- Start a Firebase account, then create a project for this little activity. I trust you can figure this out using google.
- Install Firebase tools (npm install -g firebase-tools), login (firebase login) and initiate the functions while you are in your project's folder (firebase init functions). Follow the instructions.
- Now you have a nifty little folder in your app that holds your functions and an index.js file that holds the first function you will be using. Just uncomment the helloWorld function! But ugh, what kind of weird language is that written in?
- We are going to have to make this work in React. First off, you are going to have to make it an onCall function if you are using React and you can't send your response back using response.send. . . This needs a return:
- Create a firebase.js file in your src directory. Secure the config information in your precious .env file so it provides a little difficulty to steal. And now you are thinking that I just told you that your API Keys need to be secure. The Firebase API is slightly different. If you are using secure API Keys, listen to this man on how to secure them!
- Find an inconspicuous place in one of your exported components and create a variable that points to your firebase function. You can then call your function using this variable, then log the value to the console. The data comes in as an object, so you will have to dig one step deeper, into the 'data' key.
- Push your functions to firebase using the command firebase deploy --only functions.
- The results are in!
- Firebase currently uses Node.js 6, which is a pain when trying to write async/await functions. These are typically much easier to understand than promise.then functions for many of the junior developers I talk to. Fortunately, you can make firebase accept Node.js 8 as its master opening your package.json file in your Functions folder and adding the following line:
- Write your API function in the index.js of your Function folder: I'm not going to go through all the trials I had in writing my API call to Yelp. I'm just going to give you the code and you can reapply it to most API calls that use Headers. If you are a master at React API calls, you'll notice Authorization is in quotes. Took me a long time to figure that out. You'll see that my API call only returns tacos, that is because I think tacos are the only thing that are important. You'll have to adjust your req call to add additional variables.
- What does the following line mean? functions.config().yelp.key calls your API key from the config file of your functions library. You save it by using your command prompt in the functions folder and typing firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID".
- Get out your console.log hat and test stuff out till you get something similar to the following code to work. Also, aren't async/await functions beautiful.
I know, you are blown away and hungry for tacos. Feel free to comment or send me an e-mail or give me a job.
Top comments (9)
This is actually quite misleading. While it is possible to grab your API key from your site, it is 100% safe to leave this key in the open. It is a public key and the tutorials instruct you to do so.
The way to actually secure your real-time database or Firestore on Firebase is to set rules for accessing your database based on information such as
request.userIdor whether or not they've been granted access to a group. If you don't do this your server is very much still open to attack.
This being said, to do more complicated manipulation of your database, you should use Firebase functions, not because of your API key, but rather, because exposing your business logic to the world is dangerous and could be easily manipulated to provide different, potentially harmful, results.
I am talking about API keys that are meant to be private. I even discuss how the Firebase API key and some other publishable API keys are perfectly fine in client-side code. There are a couple of links in the post that justify leaving the Firebase API key on client-side code.
It would be very helpful if you added that this information is straight from the docs. The link is here: firebase.google.com/docs/functions...
Hmmm. That is only a very small part of the tutorial above, it doesn't hit on how to make any of these functions work in React for people who may be new to the tools. Really, all that tells you how to do is set your environmental variables.
Heads-up, your portfolio link is broken.
Grabbing API Keys from code hosted publicly shouldn't be an issue. Your rules should guard your databases (Firestore, Firestorage), CORS should guard Auth and Functions.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.