Protecting Your Tokens, API Keys and Secrets

Public? Private? Wat?

Oct 27th 201819 days ago

credit: dayne-topkin-78982-unsplash.jpg

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 use a custom server (e.g. Node/Express/Heroku) in order to hide (proxy) requests to 3rd party API services.
  • 🌍 Non-secret keys describes keys which can be sent to the browser.


🔒 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

Handle Secrets Safely

Related Article: Using dotenv securely in NodeJS

Quick Overview

Complete the following steps to eliminate secrets from your code:

  1. Replace hard-coded keys with environment variables. e.g. process.env.API_SECRET
  2. Use a library like dotenv along with a .env file. Add your previously hard-coded secrets to the .env file.
  3. 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.


🌍 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!