Documentation
¶
Overview ¶
Package apikeys provides API key authentication, lifecycle management, and resolution into GoModularAuth Core Principal semantics.
Package apikeys implements cryptographically secure API key issuance, scoping, and validation.
Index ¶
- Constants
- Variables
- func ConstantTimeEqual(a, b string) bool
- func DummyHashVerification(rawKey string) bool
- func GenerateID(prefix string) string
- func GenerateRawKey(prefix string) (rawKey string, publicPrefix string, keyHash string, err error)
- func HashKey(rawKey string) string
- func RegisterSchema(s *schema.Schema) error
- func VerifyKey(rawKey string, expectedHash string) bool
- func WithAPIKey(ctx context.Context, key *APIKey) context.Context
- type APIKey
- func (k *APIKey) HasAllPermissions(permissions ...string) bool
- func (k *APIKey) HasAllScopes(scopes ...string) bool
- func (k *APIKey) HasAnyPermission(permissions ...string) bool
- func (k *APIKey) HasAnyScope(scopes ...string) bool
- func (k *APIKey) HasPermission(permission string) bool
- func (k *APIKey) HasScope(scope string) bool
- func (k *APIKey) IsActive(now time.Time) bool
- func (k *APIKey) IsExpired(now time.Time) bool
- func (k *APIKey) IsRevoked() bool
- type APIKeys
- type AuthOption
- type AuthResult
- type AuthenticatedPayload
- type Config
- type CreateInput
- type CreateResult
- type CreatedPayload
- type DeletedPayload
- type Hooks
- func (h *Hooks) AfterAuthenticate(fn func(ctx context.Context, res *AuthResult))
- func (h *Hooks) AfterCreate(fn func(ctx context.Context, key *APIKey))
- func (h *Hooks) AfterRevoke(fn func(ctx context.Context, key *APIKey))
- func (h *Hooks) AfterRotate(fn func(ctx context.Context, res *RotateResult))
- func (h *Hooks) BeforeAuthenticate(fn func(ctx context.Context, rawKey *string) error)
- func (h *Hooks) BeforeCreate(fn func(ctx context.Context, in *CreateInput) error)
- func (h *Hooks) BeforeRevoke(fn func(ctx context.Context, keyID *string) error)
- func (h *Hooks) BeforeRotate(fn func(ctx context.Context, keyID *string) error)
- type ListFilter
- type Module
- type Option
- func WithBruteForceProtection(maxAttempts int, window time.Duration) Option
- func WithCacheTTL(d time.Duration) Option
- func WithDefaultExpiresIn(d time.Duration) Option
- func WithKeyPrefix(p string) Option
- func WithSubjectStrategy(s SubjectStrategy) Option
- func WithTouchLastUsedThreshold(d time.Duration) Option
- type RevokedPayload
- type RotateOption
- func WithGracePeriod(d time.Duration) RotateOption
- func WithNewExpiresIn(d time.Duration) RotateOption
- func WithNewMetadata(meta map[string]string) RotateOption
- func WithNewName(name string) RotateOption
- func WithNewPermissions(perms []string) RotateOption
- func WithNewScopes(scopes []string) RotateOption
- type RotateResult
- type RotatedPayload
- type SubjectStrategy
Constants ¶
const ( // DefaultKeyPrefix is the default prefix prepended to issued API keys. DefaultKeyPrefix = "gma_" // EntropyBytes is the number of cryptographically secure random bytes generated for each key (256 bits). EntropyBytes = 32 // PublicPrefixLength defines how many characters from the start of rawKey are retained for human display. PublicPrefixLength = 12 )
const ( EventAPIKeyCreated auth.EventName = "apikeys.created" EventAPIKeyRevoked auth.EventName = "apikeys.revoked" EventAPIKeyRotated auth.EventName = "apikeys.rotated" EventAPIKeyAuthenticated auth.EventName = "apikeys.authenticated" EventAPIKeyDeleted auth.EventName = "apikeys.deleted" )
Event names emitted by the apikeys module.
const (
ModelAPIKeys = "api_keys"
)
const PluginID = "apikeys"
PluginID is the unique identifier for this plugin module in GoModularAuth.
Variables ¶
var ( // ErrInvalidKey is returned when the provided API key token is malformed, unrecognized, or fails verification. ErrInvalidKey = errors.New("apikeys: invalid API key") // ErrKeyNotFound is returned when the requested API key ID does not exist. ErrKeyNotFound = errors.New("apikeys: API key not found") // ErrKeyRevoked is returned when attempting to authenticate or use an API key that has been revoked. ErrKeyRevoked = errors.New("apikeys: API key has been revoked") // ErrKeyExpired is returned when an API key has passed its expiration timestamp. ErrKeyExpired = errors.New("apikeys: API key has expired") // ErrInsufficientScope is returned when an authenticated API key lacks one or more required scopes. ErrInsufficientScope = errors.New("apikeys: insufficient scope") // ErrInsufficientPermission is returned when an authenticated API key lacks one or more required permissions. ErrInsufficientPermission = errors.New("apikeys: insufficient permission") // ErrRateLimited is returned when API key verification attempts exceed rate limits (brute-force defense). ErrRateLimited = errors.New("apikeys: rate limit exceeded, authentication throttled") // ErrInvalidInput is returned when creation, rotation, or update arguments fail domain validation. ErrInvalidInput = errors.New("apikeys: invalid input") // ErrConflict is returned when an API key constraint is violated (e.g. duplicate key ID). ErrConflict = errors.New("apikeys: API key conflict") // ErrStoreRequired is returned during plugin initialization when no Store adapter is configured. ErrStoreRequired = errors.New("apikeys: store adapter is required") )
Functions ¶
func ConstantTimeEqual ¶
ConstantTimeEqual performs constant-time comparison between two string values.
func DummyHashVerification ¶
DummyHashVerification simulates key verification timing against a fixed dummy hash to equalize response timing when a requested key does not exist.
func GenerateID ¶
GenerateID produces a random hexadecimal identifier with an optional prefix (e.g. "ak_...").
func GenerateRawKey ¶
GenerateRawKey produces a new cryptographically secure random API key, its public prefix, and its SHA-256 hash representation. The raw key must be returned to the caller immediately and NEVER stored in persistence.
func RegisterSchema ¶
RegisterSchema registers the api_keys model into the compiled schema.
Types ¶
type APIKey ¶
type APIKey struct {
ID string `json:"id"`
Name string `json:"name"`
Prefix string `json:"prefix"`
KeyHash string `json:"key_hash"`
UserID string `json:"user_id,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
ServiceID string `json:"service_id,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Permissions []string `json:"permissions,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
RevokedAt *time.Time `json:"revoked_at,omitempty"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
LastUsedIP string `json:"last_used_ip,omitempty"`
LastUsedUA string `json:"last_used_ua,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
APIKey represents the persistent record of an API key. Secret tokens are NEVER stored; only KeyHash (SHA-256) and Prefix are kept.
func APIKeyFrom ¶
APIKeyFrom retrieves the APIKey stored in ctx, if present.
func (*APIKey) HasAllPermissions ¶
HasAllPermissions checks if the key contains all specified permissions.
func (*APIKey) HasAllScopes ¶
HasAllScopes checks if the key contains all specified scopes.
func (*APIKey) HasAnyPermission ¶
HasAnyPermission checks if the key contains at least one of the specified permissions.
func (*APIKey) HasAnyScope ¶
HasAnyScope checks if the key contains at least one of the specified scopes.
func (*APIKey) HasPermission ¶
HasPermission checks if the key contains the specified permission.
type APIKeys ¶
type APIKeys interface {
// Create generates and stores a new API key, returning the plaintext key once.
Create(ctx context.Context, in CreateInput) (*CreateResult, error)
// Get retrieves an API key by its unique ID.
Get(ctx context.Context, id string) (*APIKey, error)
// List queries API keys based on ownership filters.
List(ctx context.Context, filter ListFilter) ([]*APIKey, error)
// Revoke immediately revokes an API key and purges it from any cache.
Revoke(ctx context.Context, id string) error
// Rotate replaces an existing key with a newly generated key, optionally preserving
// the old key during a grace period.
Rotate(ctx context.Context, id string, opts ...RotateOption) (*RotateResult, error)
// Authenticate validates a raw API key, checks expiration and scopes,
// updates last-used telemetry, and resolves to an auth.Principal.
Authenticate(ctx context.Context, rawKey string, opts ...AuthOption) (*AuthResult, error)
// Delete permanently deletes an API key record and invalidates cache entries.
Delete(ctx context.Context, id string) error
// PurgeExpired deletes expired and revoked keys from persistence.
PurgeExpired(ctx context.Context) (int, error)
// Hooks provides access to the API key workflow lifecycle hooks.
Hooks() *Hooks
}
APIKeys defines the strongly typed capability interface for API key authentication.
type AuthOption ¶
type AuthOption func(*authConfig)
AuthOption configures authentication validation and telemetry.
func WithIPAddress ¶
func WithIPAddress(ip string) AuthOption
WithIPAddress records the client IP address on the API key's last used telemetry.
func WithRequiredPermissions ¶
func WithRequiredPermissions(perms ...string) AuthOption
WithRequiredPermissions enforces that the authenticated key must possess all given permissions.
func WithRequiredScopes ¶
func WithRequiredScopes(scopes ...string) AuthOption
WithRequiredScopes enforces that the authenticated key must possess all given scopes.
func WithUserAgent ¶
func WithUserAgent(ua string) AuthOption
WithUserAgent records the client User-Agent header on the API key's last used telemetry.
type AuthResult ¶
AuthResult is returned when an API key is successfully authenticated. In accordance with GoModularAuth architecture, API key authentication resolves directly to an auth.Principal and does NOT create or return an HTTP User Session.
type AuthenticatedPayload ¶
type AuthenticatedPayload struct {
ID string `json:"id"`
Prefix string `json:"prefix"`
UserID string `json:"user_id,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
ServiceID string `json:"service_id,omitempty"`
IPAddress string `json:"ip_address,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
PrincipalType string `json:"principal_type"`
Subject string `json:"subject"`
}
AuthenticatedPayload is the payload published on EventAPIKeyAuthenticated.
type Config ¶
type Config struct {
// KeyPrefix is the default prefix prepended to issued API keys (defaults to "gma_").
KeyPrefix string
// DefaultExpiresIn sets a default expiration duration if none is specified at creation.
DefaultExpiresIn time.Duration
// CacheTTL defines how long active keys are retained in cache (defaults to 5m).
CacheTTL time.Duration
// MaxFailedAttempts specifies the maximum failed verification attempts before throttling.
MaxFailedAttempts int
// BruteForceWindow is the evaluation window for failed verification attempts.
BruteForceWindow time.Duration
// SubjectStrategy controls how auth.Principal.Subject is populated.
SubjectStrategy SubjectStrategy
// TouchLastUsedThreshold prevents database write amplification by updating LastUsedAt
// only if the key was last used longer ago than this threshold (defaults to 1m).
TouchLastUsedThreshold time.Duration
}
Config configures the API keys plugin module.
type CreateInput ¶
type CreateInput struct {
Name string
UserID string
OrganizationID string
ServiceID string
Scopes []string
Permissions []string
Metadata map[string]string
ExpiresAt *time.Time
ExpiresIn time.Duration
Prefix string
}
CreateInput contains parameters required to create an API key.
type CreateResult ¶
CreateResult returns the newly persisted API key record along with the single-use plaintext key secret.
type CreatedPayload ¶
type CreatedPayload struct {
ID string `json:"id"`
Name string `json:"name"`
Prefix string `json:"prefix"`
UserID string `json:"user_id,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
ServiceID string `json:"service_id,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Permissions []string `json:"permissions,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
}
CreatedPayload is the payload published on EventAPIKeyCreated. Secrets and full key hashes are strictly omitted.
type DeletedPayload ¶
type DeletedPayload struct {
ID string `json:"id"`
Prefix string `json:"prefix"`
UserID string `json:"user_id,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
ServiceID string `json:"service_id,omitempty"`
}
DeletedPayload is the payload published on EventAPIKeyDeleted.
type Hooks ¶
type Hooks struct {
// contains filtered or unexported fields
}
Hooks provides lifecycle interception points for the API keys module workflows.
func (*Hooks) AfterAuthenticate ¶
func (h *Hooks) AfterAuthenticate(fn func(ctx context.Context, res *AuthResult))
AfterAuthenticate runs after credentials are successfully verified and telemetry updated.
func (*Hooks) AfterCreate ¶
AfterCreate runs after an API key is persisted and published.
func (*Hooks) AfterRevoke ¶
AfterRevoke runs after an API key is revoked and cache invalidated.
func (*Hooks) AfterRotate ¶
func (h *Hooks) AfterRotate(fn func(ctx context.Context, res *RotateResult))
AfterRotate runs after rotation finishes, returning both old and new keys.
func (*Hooks) BeforeAuthenticate ¶
BeforeAuthenticate runs before validating candidate credentials.
func (*Hooks) BeforeCreate ¶
func (h *Hooks) BeforeCreate(fn func(ctx context.Context, in *CreateInput) error)
BeforeCreate runs before an API key is validated and persisted.
func (*Hooks) BeforeRevoke ¶
BeforeRevoke runs before an API key revocation is applied in the store.
type ListFilter ¶
type ListFilter struct {
UserID string
OrganizationID string
ServiceID string
IncludeRevoked bool
Limit int
Offset int
}
ListFilter specifies filter and pagination criteria for querying API keys.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module implements auth.PluginModule and auth.SchemaProvider for API key authentication using plugin-sdk.
type Option ¶
type Option func(*Config)
Option modifies Config.
func WithBruteForceProtection ¶
WithBruteForceProtection configures rate limiting on failed key verification attempts.
func WithCacheTTL ¶
WithCacheTTL configures the TTL for cached API keys.
func WithDefaultExpiresIn ¶
WithDefaultExpiresIn sets the default expiration lifetime for keys created without explicit expiration.
func WithKeyPrefix ¶
WithKeyPrefix sets the default prefix for newly generated API keys.
func WithSubjectStrategy ¶
func WithSubjectStrategy(s SubjectStrategy) Option
WithSubjectStrategy configures how the principal subject is resolved.
func WithTouchLastUsedThreshold ¶
WithTouchLastUsedThreshold configures the minimum interval between LastUsedAt database writes.
type RevokedPayload ¶
type RevokedPayload struct {
ID string `json:"id"`
Prefix string `json:"prefix"`
UserID string `json:"user_id,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
ServiceID string `json:"service_id,omitempty"`
RevokedAt time.Time `json:"revoked_at"`
}
RevokedPayload is the payload published on EventAPIKeyRevoked.
type RotateOption ¶
type RotateOption func(*rotateConfig)
RotateOption configures an API key rotation.
func WithGracePeriod ¶
func WithGracePeriod(d time.Duration) RotateOption
WithGracePeriod specifies how long the old API key remains valid before expiring. If zero or not provided, the old key is immediately revoked.
func WithNewExpiresIn ¶
func WithNewExpiresIn(d time.Duration) RotateOption
WithNewExpiresIn sets a new relative expiration duration on the rotated key.
func WithNewMetadata ¶
func WithNewMetadata(meta map[string]string) RotateOption
WithNewMetadata overrides the custom metadata on the rotated key.
func WithNewName ¶
func WithNewName(name string) RotateOption
WithNewName overrides the name of the newly generated key during rotation.
func WithNewPermissions ¶
func WithNewPermissions(perms []string) RotateOption
WithNewPermissions overrides the permissions granted to the rotated key.
func WithNewScopes ¶
func WithNewScopes(scopes []string) RotateOption
WithNewScopes overrides the scopes granted to the rotated key.
type RotateResult ¶
RotateResult contains the newly issued key, its plaintext secret, and the updated old key.
type RotatedPayload ¶
type RotatedPayload struct {
OldKeyID string `json:"old_key_id"`
NewKeyID string `json:"new_key_id"`
Prefix string `json:"prefix"`
UserID string `json:"user_id,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
ServiceID string `json:"service_id,omitempty"`
GracePeriod *time.Time `json:"grace_period_expires_at,omitempty"`
}
RotatedPayload is the payload published on EventAPIKeyRotated.
type SubjectStrategy ¶
type SubjectStrategy string
SubjectStrategy defines how an API key resolves its auth.Principal.Subject.
const ( // SubjectStrategyKeyID sets Principal.Subject to the unique API key ID (default). SubjectStrategyKeyID SubjectStrategy = "key_id" // SubjectStrategyOwner prioritizes UserID, then ServiceID, then KeyID as Principal.Subject. SubjectStrategyOwner SubjectStrategy = "owner" )
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package cache provides caching and brute force prevention abstractions for the API keys module.
|
Package cache provides caching and brute force prevention abstractions for the API keys module. |
|
Package plugins exposes capability aliases for GoModularAuth plugins.
|
Package plugins exposes capability aliases for GoModularAuth plugins. |