4.0.0 • Published 8 months ago

@bencmbrook/prefixed-api-key v4.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

Generate Prefixed API Keys

This is a fork of seamapi/prefixed-api-key. Seam-style API Keys have many advantages:

  • Double clicking the api key selects the entire api key
  • The alphabet is standard across languages thanks to the base58 RFC and its usage in cryptocurrencies
  • They are shorter than hex and base32 api keys
  • They have prefixes allowing secret scanning by github
  • They have a hashed component so the server doesn't need to store the api key (reducing attack surface)
  • They have unhashed Key IDs which can be mutually used by the server and key bearer/customer to identify the api key
  • They default to roughly the same number of entropy bits as UUIDv4

The Format

API keys look like this:

myapp_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG

Let's break down each component of the API key...

myapp ..._...  BRTRKFsL ..._...  51FwqftsmMDHHbJAMEXXHCgG
^              ^                 ^
Prefix         Key ID            Secret
  • The Prefix is used to identify the company or service creating the API Key. This is very helpful in secret scanning.
  • The Key ID is stored by both the server and the key bearer/customer, it can be used to identify an API key in logs or displayed on a customer's dashboard. An apiKey can be blocklisted by its Key ID.
  • The Secret is how we authenticate this key. The secret is never stored on the server, but a hash of it is stored on the server. When we receive an incoming request, we search our database for key_id and hash(secret).

Getting Started

import { generateAPIKey } from '@bencmbrook/prefixed-api-key';

const key = await generateAPIKey({ keyPrefix: 'myapp' });

// Store the key.secretHash and key.keyId in your database and give
// key.apiKey to your customer.

console.log(key);
/*
{
  keyId: 'BRTRKFsL',
  secretHash: 'd70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37',
  apiKey: 'myapp_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG'
}
*/

Utility Methods

import {
  checkAPIKey,
  extractKeyId,
  extractSecret,
  getAPIKeyObject,
  hashSecret,
} from '@bencmbrook/prefixed-api-key';

hashSecret('51FwqftsmMDHHbJAMEXXHCgG');
// "d70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37"

extractSecret('myapp_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG');
// "51FwqftsmMDHHbJAMEXXHCgG"

extractKeyId('myapp_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG');
// "BRTRKFsL"

getAPIKeyObject('myapp_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG');
/*
{
  keyId: 'BRTRKFsL',
  secretHash: 'd70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37',
  apiKey: 'myapp_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG'
}
*/

checkAPIKey(
  'myapp_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG',
  'd70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37',
);
// true
4.0.0

8 months ago

3.0.1

8 months ago

3.0.0

8 months ago

2.0.2

8 months ago

2.0.0

8 months ago