Documentation
¶
Overview ¶
Package apikey provides API key generation, storage, and HTTP authentication.
Keys are generated as prefixed, base62-encoded random strings (e.g. "sk_live_4Xy…"). Only a SHA-256 hash of the key is ever stored, so a compromised database cannot expose the plaintext keys.
Quick start:
store := apikey.NewMemoryStore()
svc := apikey.NewService(store)
// Issue a key (e.g. on account creation)
key, err := svc.Issue(apikey.IssueOptions{Name: "ci-pipeline", Prefix: "sk_live"})
fmt.Println(key.Plaintext) // show once, never store
// Authenticate HTTP requests
mux.Handle("/api/", apikey.Middleware(svc)(handler))
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidKey = errors.New("apikey: invalid or unrecognised key") ErrRevokedKey = errors.New("apikey: key has been revoked") ErrExpiredKey = errors.New("apikey: key has expired") ErrKeyNotFound = errors.New("apikey: key not found") )
Sentinel errors.
Functions ¶
func Middleware ¶
Middleware returns an HTTP middleware that authenticates requests via an API key. The key is read from the Authorization header ("Bearer <key>") or the X-API-Key header. On success, the Key record is stored in the request context.
func SubjectFrom ¶
SubjectFrom returns the Subject field of the key stored in the context, or an empty string when absent.
Types ¶
type IssueOptions ¶
type IssueOptions struct {
// Prefix is prepended to the plaintext key (e.g. "sk_live", "sk_test").
// A separator "_" is added automatically between prefix and random part.
Prefix string
// Name is a human-readable label stored alongside the key hash.
Name string
// Subject associates the key with an entity (e.g. a user ID).
Subject string
// Metadata holds arbitrary key-value data to store with the key.
Metadata map[string]any
// ExpiresIn sets an optional TTL. Zero means the key never expires.
ExpiresIn time.Duration
// Length is the number of random base62 characters (default: 40).
Length int
}
IssueOptions configures a newly issued key.
type IssuedKey ¶
type IssuedKey struct {
// Plaintext is the full key string to present to the user.
// It is never stored internally — lose it and you lose the key.
Plaintext string
// Key is the stored record (without the plaintext).
Key *Key
}
IssuedKey is returned by Service.Issue. It holds both the plaintext key (shown to the user exactly once) and the stored Key record.
type Key ¶
type Key struct {
// ID is a unique opaque identifier (derived from the key hash).
ID string
// Hash is the hex-encoded SHA-256 of the plaintext key.
Hash string
// Name is a human-readable label (e.g. "ci-pipeline").
Name string
// Subject associates the key with a user or service (e.g. user ID).
Subject string
// Metadata holds arbitrary application data.
Metadata map[string]any
// CreatedAt is when the key was issued.
CreatedAt time.Time
// ExpiresAt is the optional expiry time. Nil means the key never expires.
ExpiresAt *time.Time
// Revoked is true when the key has been explicitly revoked.
Revoked bool
}
Key is the full representation of an API key stored in the backend.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is a thread-safe in-memory Store.
func NewMemoryStore ¶
func NewMemoryStore() *MemoryStore
NewMemoryStore returns an initialised MemoryStore.
func (*MemoryStore) ListBySubject ¶
func (s *MemoryStore) ListBySubject(subject string) ([]*Key, error)
func (*MemoryStore) Revoke ¶
func (s *MemoryStore) Revoke(id string) error
func (*MemoryStore) Save ¶
func (s *MemoryStore) Save(k *Key) error
type MiddlewareOption ¶
type MiddlewareOption func(*middlewareCfg)
MiddlewareOption configures apikey middleware behaviour.
func WithErrorHandler ¶
func WithErrorHandler(fn func(http.ResponseWriter, *http.Request, error)) MiddlewareOption
WithErrorHandler replaces the default 401 error response handler.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service manages API key lifecycle.
func NewService ¶
NewService creates a Service backed by the given Store.
func (*Service) Issue ¶
func (s *Service) Issue(opts IssueOptions) (*IssuedKey, error)
Issue generates a new API key, hashes it, and persists the record. The caller must present IssuedKey.Plaintext to the end user; it is not recoverable after this call returns.
type Store ¶
type Store interface {
// Save persists a new key record.
Save(k *Key) error
// GetByHash retrieves a key by its SHA-256 hash. Returns ErrKeyNotFound
// when absent.
GetByHash(hash string) (*Key, error)
// GetByID retrieves a key by its ID. Returns ErrKeyNotFound when absent.
GetByID(id string) (*Key, error)
// Revoke marks the key with the given ID as revoked.
Revoke(id string) error
// ListBySubject returns all keys associated with the given subject.
ListBySubject(subject string) ([]*Key, error)
}
Store persists API key records. Implement this interface to back the service with PostgreSQL, Redis, etc.