Documentation
¶
Overview ¶
Package apikey issues and verifies opaque API keys for authcore.
What it is for ¶
API keys authenticate machines — a CLI, a service, a webhook caller — where a username/password or a short-lived JWT does not fit. authcore generates a high-entropy opaque key, returns a hash for you to store, and verifies a presented key against that hash in constant time. The library never stores anything; you own the database.
Key shape ¶
<prefix>_<id>_<secret>
- prefix — a short fixed tag (default "ak") so a leaked key is recognisable
in logs and can be scanned for.
- id — a random public identifier. Store it in plaintext and use it as
the database lookup key, so verification is an O(1) row fetch, not a scan.
- secret — 256 bits of CSPRNG output, hex-encoded. Only its keyed hash is
stored.
Storage model ¶
The key is high-entropy random, so it is hashed with keyed HMAC-SHA256 (fast, constant-time-verifiable, peppered with the library's managed secret) rather than a slow password hash — a per-request API call must not pay Argon2id cost, and a 256-bit random key has no need of it.
auth, _ := authcore.New(authcore.DefaultConfig())
keyMod, _ := apikey.New(auth)
// Issue — show key.Key to the user ONCE; store key.ID and key.Hash.
key, _ := keyMod.Generate()
db.StoreAPIKey(key.ID, key.Hash, userID)
// Verify — extract the id, fetch the row, compare in constant time.
id, err := keyMod.ParseID(presented)
if err != nil { return http.StatusUnauthorized }
row, err := db.FindAPIKey(id)
if err != nil || !keyMod.Verify(presented, row.Hash) { return http.StatusUnauthorized }
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidConfig is returned by New when the provided Config fails // validation (e.g. an empty or malformed Prefix). // // Safety: INTERNAL — a startup/programming error. Treat as a 500. ErrInvalidConfig = errors.New("apikey: invalid configuration") // ErrInvalidKey is returned by ParseID when the presented key is not a // well-formed key for this module (wrong prefix, structure, or id). // // Safety: INTERNAL — return a generic "unauthorized" to the client; never // echo back why the key was rejected. ErrInvalidKey = errors.New("apikey: malformed key") )
Sentinel errors returned by the apikey package. Use errors.Is to check for these in calling code.
Functions ¶
This section is empty.
Types ¶
type APIKey ¶
type APIKey struct {
// contains filtered or unexported fields
}
APIKey is the opaque API-key module.
Construct one instance at application startup using New and share it across goroutines. APIKey is safe for concurrent use after construction.
func New ¶
New creates an APIKey module.
cfg is optional — omit it for the default key prefix ("ak"):
keyMod, err := apikey.New(auth)
keyMod, err := apikey.New(auth, apikey.Config{Prefix: "svc"})
func (*APIKey) Generate ¶
func (a *APIKey) Generate() (*GeneratedKey, error)
Generate mints a new opaque API key. The id and secret are independent CSPRNG draws; the returned Hash is what you store.
func (*APIKey) Hash ¶
Hash returns the keyed HMAC-SHA256 digest of key. Use it to recompute the stored value (it matches GeneratedKey.Hash for the same key).
func (*APIKey) ParseID ¶
ParseID extracts the public identifier from a presented key without verifying it, so you can fetch the stored hash before the constant-time comparison.
It returns ErrInvalidKey if key is not a well-formed key for this module (wrong prefix, wrong structure, or a malformed id).
type Config ¶
type Config struct {
// Prefix is the fixed tag at the start of every key (e.g. "ak" -> "ak_...").
// Pick something short and product-specific so a leaked key is recognisable
// in logs and secret scanners. Must be 1–16 lowercase letters or digits and
// must not contain "_" (the field separator).
//
// Defaults to "ak".
Prefix string
}
Config holds the apikey module configuration.
type GeneratedKey ¶
type GeneratedKey struct {
// Key is the full opaque API key to hand to the caller, once.
Key string
// ID is the public identifier embedded in Key. Store it and use it to look
// up the stored hash on verification.
ID string
// Hash is the keyed HMAC-SHA256 digest of Key. Store only this.
Hash string
}
GeneratedKey is the result of Generate.
Show Key to the user exactly once — it is never recoverable afterwards. Persist ID (plaintext, the lookup key) and Hash (never the raw key).