Treat an API key like a password that a machine uses.
Creating keys:
- Use a secure random generator with at least 128 bits, for example
crypto.randomBytes(32).toString("base64url"). - Add a readable prefix like
sk_live_. People can recognise the key, and secret scanners (such as GitHub's) can find leaked keys by the prefix.
Storing keys:
- Store only a hash of the key, never the key itself.
- A fast hash like SHA-256 is fine here, because the key is long and random. Slow hashes like bcrypt are for short, guessable passwords, and they would slow down every API call.
- Show the full key once, when it's created. After that, show only the prefix and the last 4 characters.
Managing keys:
- Give each key scopes (permissions) and its own rate limit.
- Allow two active keys at once, so customers can rotate without downtime.
- Support expiry and instant revoking.
- Record when each key was last used, and audit-log creating and revoking keys.
- Accept keys only in a header such as
Authorization. Never accept them in the URL, because URLs end up in logs and browser history.
- Generate keys with a secure random generator and at least 128 bits.
- A readable prefix helps people and secret scanners recognise leaked keys.
- Store only a hash, and SHA-256 is enough for long random keys.
- Show the full key once, and support scopes, rotation, expiry and revoking.
- Accept keys in a header, never in the URL.
Read more