I have a problem with an old FCC project (the weather API one) I published 4 years ago and just found out I hard codded the API keys in the projects JS file.
The project is simply, one HTML file, a css file, and a JS file where I coded the API calls.
I want to replace the the API key in the following code for example with a an environment secret on github
var photoSizeApi = "https://api.flickr.com/services/rest/?method=flickr.photos.getSizes&photo_id=" + id + "&format=json&nojsoncallback=1&api_key=ec0ca2ee160a19f017eb3ddcbda7ccb4";
The thing I want to figure out is, how do I conceal or hide the API keys and prevent them from showing in the browser devtools? I just learned about github workflows and actions and using secrets…but still I can’t think of how to make it concealed in the frontend?
You can’t hide things on the frontend. No matter what you do, a clever hacker can get at them.
In a real world app, you would create a microservice to handle that. Your frontend would call your microservice which would make the call with your API key, get it’s value back, and then return it to the frontend. That way your frontend never sees the API key.
Andrew’s suggestion works if you are in a Node environment.
For these little projects I wouldn’t worry about it too much. FCC now provides a weather microservice so you don’t have to worry about it.
It’s worth bringing up that there are some API’s that are built to be accessible from the client-side. Usually these have other protections to help protect the API from being abused. Examples would be Google Analytics and client-side Firebase libraries.
If the docs specify how to use the API from the client-side, then it should be ok to use in such a situation. If it isn’t, then yes using a secure back-end would be the right way to go.
Specifically for github-actions + secrets, there is a way around the lack of a backend depending on the use-case. Take for example, you want to get some data from an API every time you re-build your client-side, the github-actions is a secure runtime environment, can get the data from the API and save the data into a static file that is deployed with your application later. (Usually seen in JAMStack type builds) This might not work for something like the weather API, where the end user wants to technically access the API thru your app, but it could work for some use-cases depending on what your doing, so its worth keeping in mind.
When building a container for a single-page application using any modern JavaScript framework (such as Angular, React, or Vue.js), you might find that the configuration settings are different depending on where the container will run. A typical case would be the base URL for your API, which will differ depending on whether you are testing the application or deploying it into production. Developers usually solve this problem using environment variables.
Environment variables typically work on the backend because that is where code runs. But what if your application lives in the user’s browser? There are many ways around this limitation. In some cases, you might build a server whose endpoint holds the necessary parameters. Another workaround is to use PHP to inject the environment variables as globals in the JavaScript code. Both of these options work, but it would be ideal to inject the environment variables as part of the container build process. That way, you don’t have to change the codebase, and you can still deliver the application content using a static web server like NGINX.
This article shows you how to inject environment variables directly into your codebase as you build your container.