
Photo by Scott Webb on Unsplash
The Correct 2-Key Strategy
How to protect developer API keys from leaking into client-side code.
2024-09-03T10:31-07:00
At first I thought I found a way to protect developer API keys – or keys open to localhost – from leaking into client-side code. Boy, was I wrong.
Webpack's compiler conveniently removes unused code, but I had accidentally configured my JavaScript to use both the development and production API keys after compiling. Setting the gatekeeping variable IS_DEVELOPMENT to false had no effect at build time. When I think about it now, it makes sense. JavaScript needs both API keys at runtime for the boolean to even know which one to pick (duh).
I can't use a gatekeeping boolean variable to hide the development key from my client-side code. However, there is another way – although it's a bit more complex (ain't that how web development goes). Here are the steps I took to completely hide my development API keys that are open to localhost:
- Create two files: api-key-dev.js and api-key-prod.js (for development and production, respectively)
- Add the development and production API keys to their respective files
- Export each API key with the same variable name. Example:
export { apiKey } - Import the development API key where needed. Example for client-file.js:
import { apiKey } from "./api-key-dev.js" - Create a command-line file (shell ".sh" file for Mac, or batch ".bat" file for Windows) that has these lines of code:
# Mac shell script replacing the development API key import with the production one: sed -i '' 's/api-key-dev.js/api-key-prod.js/g' client-file.js # Windows batch script version: (Get-Content client-file.js) -replace 'api-key-dev.js', 'api-key-prod.js' | Out-File -encoding ASCII client-file.js # bundle/deploy/publish command(s) go here: npm run deploy # switch the production API key import back to the development one after deployment: sed -i '' 's/api-key-prod.js/api-key-dev.js/g' client-file.js # Windows batch script version: (Get-Content client-file.js) -replace 'api-key-prod.js', 'api-key-dev.js' | Out-File -encoding ASCII client-file.js - Before running the above script, make sure to add api-key-dev.js as a line in your .gitignore file to prevent it from winding up on GitHub. Also, if api-key-dev.js exists in a public directory, make sure to prevent web clients from accessing it by updating your .htaccess file directly or through your hosting service's settings. For Firebase Hosting, I would add **/api-key-dev.js to the "ignore" array under firebase.json
Now running our special script will swap out the development imports with the production ones before deployment, then switch them back afterwards, all while keeping the development API key hidden from public access.