Protecting Your Tokens, API Keys and Secrets

Public? Private? Wat?

published 5 months agoOct 27th, 2018

updated 4 months agoDec 7th, 2018

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

Unless otherwise noted, all content is copyright Dan Levy 2014-1019.