Hi there! How’ve you been? I hope well!
Well, this week I stumbled upon a task that required me to hide/secure my API key (e.g. Google books API key) from plain sight! One of the following things Google recommends in this page is:
Do not embed API keys directly in code!
This is important issue especially if you have limited bandwidth or limited requests or whatever. Or maybe you have paid for them. After googling around as usual I was not able to say that I have found a really good way or a worthwhile tutorial!
So, here is what I did eventually! I hope there is a better way out there but for now I am happy with this implementation! By the way, I found a really good method for storing your keys and any sensitive information in environment variables directly to your computer! Here is the link for this one:
Protect your API keys using environment variables and Node.JS
Note: the caveat for this though is that involves tweaking the client operating system in order to work and that you have to set it up locally every time you change client PC.
Solution
I found an npm package called dotenv.
.env is also a hidden file for storing key/value pairs for your application!
We can read in the documentation in the dotenv module that..
Dotenv is a zero-dependency module that loads environment variables from a
.env
file intoprocess.env
. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology.
Aha! We then need a .env file somewhere in our application so the module can read its contents to the node.js global variable process.env. Ok, but where should we put it? Reading further down we find all possible answers to the question we might have trying to implement this nice lil’ module’s task!
The root directory is the place! Hurray!
How to pass the process.env.parsed variable to our React app?
Let’s see some example first so we can see things more clearly.
Here is a dummy API key (the value is random keystrokes, do not get excited!).
The only node.js file running in our client app though is the server.js file in our root directory. The thing is that if we copy the code in the docs of the module to access the .env file contents and pass them to process.env we do not have access of this updated variable in our client side code. We can access process.env but not process.env.parsed, process.env is an empty object in this case!
Hopefully, there is another module called DefinePlugin. This one is a plugin for Webpack, so we need to visit its config file, webpack.config.js. If you have no other plugins running, you should add this section to your object.
Note that because the plugin does a direct text replacement, the value given to it must include actual quotes inside of the string itself. Typically, this is done either with either alternate quotes, such as
'"production"'
, or by usingJSON.stringify('production')
.
Note: if we do not use JSON.stringify here we get an error like the one below, when we try to access the new global constant API_KEY in our React client code:
Uncaught SyntaxError: Invalid or unexpected token
The key API_KEY is the new global constant we can access directly in our code now. Try console.log(API_KEY) and see for yourself. The value printed to the console is the value of the key/value pair we passed in our .env file.
Note: you can name everything as you please…
Conclusion
Although this method is far from bulletproof, it works nicely by hiding your api keys outside of your “visible” code (anyone with a basic knowledge of how to check .js code on a page can do this otherwise!).
Oh, one last thing we nearly forgot! What about pushing to GitHub? The solution is pretty simple for this!
You just add .env to your .gitignore file and you are set and secure to go!
If you know any other more secure method for this task, that is securing your API keys, please feel free to drop a comment below pointing to a solution or add a comment explaining what is what! You will help me and others visiting this page to do a better job and become better developers! I really appreciate any addition or fix or comment or even rebuke! Really!!!
Cheers!