Protecting Your Tokens, API Keys and Secrets
Public? Private? Wat?
When to protect your tokens?
Securing API keys & tokens is critically important!
One mistake can lead to lost control of your server and data to hackers!
It shouldn’t be so difficult determining if any particular token must be hidden - even based on official documentation!
It is often made worse with the soup of related terms you’ll encounter: tokens, keys, credentials, secrets, private, and public.
Let’s re-frame this as between secret
and non-secret
.
- 🔒
Secret keys
MUST be kept hidden. Generally they should NEVER leave your private server (or service - like heroku, netlify or travis-ci). - 🌍
Non-secret keys
describes strings which could be shared freely and included in browser requests.
🔒 Secret keys
** ‼️ Important:** Secret keys
MUST be ignored by Git AND omitted in all browser code. How to use dotenv
How do you know when you’re dealing with a Secret key
?
👍 Rule-of-thumb: servers which return CORS errors
lack browser support. It strongly indicates you MUST proxy the service, treating it as though secret
.
👍 Rule-of-thumb: costly services should (almost) always be proxied or hidden.
👍 Rule-of-thumb: if you do a write operation (file upload, insert db row), you could be dealing with secret keys
.
Use cases & features: Secret
keys
- Long-term authorization (credentials, access tokens, JSON Web Tokens)
- Short-term authorization (OAuth tokens, session store)
- Access paid/expensive services (for auth, geocoding, file storage, etc)
- Private part of public/private pair (RECAPTCHA, Stripe, Auth0)
- Service credentials (Email/SMTP, LDAP/Directory Services)
- Data encryption & integrity checking
Checklist: Handling Secrets Safely
Quick Overview
Complete the following steps to eliminate secrets from your code:
- Replace hard-coded keys with environment variables. e.g.
process.env.API_SECRET
- Use a library like
dotenv
along with a.env
file. Add your previously hard-coded secrets to the.env
file. - Add a
.env
line in your.gitignore
file!
DON’T create a
.env
file on deployed servers. Use your hosting services’ (e.g. Heroku, Netlify, AWS EC2) provided environment variable management tool: e.g. dashboard or command line.
Related Article: Using dotenv securely in NodeJS
🌍 Non-secret keys
👍 Rule-of-thumb: whenever a key must be sent to the browser in code or inline (e.g. via a <script src="https://my-api/?apiKey=123-abc-456">
tag), it’s definitely a non-secret
. A common example is Google Maps.
Use cases & features: Non-secret
keys
- Short-term access (user session IDs, JSON Web Tokens)
- Limiting API access by app/developer (for auth, geocoding, etc)
- Public part of public/private pair (RECAPTCHA, Stripe, Auth0)
- Analytics IDs
✅ Handling Non-secrets:
It’s safe to hard-code non-secret (public) keys!
Make this easier to manage long term with a shared config.js
for your app.
Example:
// config.js
module.exports = {
googleMapsKey: '123-abc'
};
// load-map.js
const config = require('./config.js');
const key = config.googleMapsKey;
const src = `//maps.googleapis.com/maps/api/js?key=${key}`;
// ...
Note: There are other Use Cases for environment variables. Some I didn’t cover: CI/CD/testing, feature flags, and runtime configuration for special environments!