apikey

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 12 Imported by: 0

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

View Source
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

func Middleware(svc *Service, opts ...MiddlewareOption) func(http.Handler) http.Handler

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

func SubjectFrom(ctx context.Context) string

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.

func KeyFrom

func KeyFrom(ctx context.Context) *Key

KeyFrom retrieves the authenticated Key from the request context. Returns nil when no key is present.

func (*Key) IsExpired

func (k *Key) IsExpired() bool

IsExpired reports whether the key has passed its expiry time.

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) GetByHash

func (s *MemoryStore) GetByHash(hash string) (*Key, error)

func (*MemoryStore) GetByID

func (s *MemoryStore) GetByID(id string) (*Key, error)

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

func NewService(store Store) *Service

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.

func (*Service) Revoke

func (s *Service) Revoke(id string) error

Revoke marks the key with the given ID as revoked.

func (*Service) Verify

func (s *Service) Verify(plaintext string) (*Key, error)

Verify checks a plaintext key string and returns the stored Key record. Returns an error if the key is invalid, revoked, or expired.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL