Help us shape the future of Go! Take the 2026 Go Developer Survey

apikey

package
v0.0.12 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2026 License: Apache-2.0, MIT Imports: 26 Imported by: 0

Documentation

Overview

Package apikey issues machine credentials sent via the X-API-KEY header, with expiry and last-used tracking. Keys are the user's own API keys; resource-server scopes live in the apiaccess module.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotFound     = errors.New("apikey: key not found")
	ErrDuplicate    = errors.New("apikey: key name already exists")
	ErrNotExpired   = errors.New("apikey: key is not expired yet")
	ErrInvalidCreds = errors.New("apikey: key is invalid or expired")
)

Errors surfaced by the store and service; the handler maps them to statuses.

Functions

func HashToken

func HashToken(token string) string

HashToken derives the stored lookup key for a token.

func NewToken

func NewToken() (string, error)

NewToken draws an opaque 256-bit token, base64url-encoded.

Types

type APIKey

type APIKey struct {
	ID                    APIKeyID   `json:"id"`
	Name                  string     `json:"name"`
	Description           *string    `json:"description,omitzero"`
	ExpiresAt             time.Time  `json:"expires_at"`
	CreatedAt             time.Time  `json:"created_at"`
	LastUsedAt            *time.Time `json:"last_used_at,omitzero"`
	ExpirationEmailSentAt *time.Time `json:"-"`
}

APIKey is one machine credential row.

type APIKeyID

type APIKeyID = typeid.TypeID[apiKeyPrefix]

Typed IDs for the api key tables: UUIDv7 suffix, snake_case prefix matching the singular table name.

type CreateParams

type CreateParams struct {
	Name        string
	Description *string
	ExpiresAt   time.Time
}

CreateParams carries the POST /api-keys fields.

func (*CreateParams) Validate

func (p *CreateParams) Validate() error

Validate checks the name and expiry.

type ListParams

type ListParams struct {
	Page
}

ListParams narrows and pages the listing; keys are scoped to the authenticated user.

type Page

type Page struct {
	Page  int
	Limit int
}

Page is the store-level paging window: plain ints with no HTTP dependency. The handler converts the request query into it.

func (Page) All

func (p Page) All() bool

All reports whether the listing skips paging (page or limit is the all marker -1).

func (Page) Offset

func (p Page) Offset() int

Offset returns the SQL offset for the current page.

type PostgresStore

type PostgresStore struct {
	// contains filtered or unexported fields
}

PostgresStore persists keys in public.api_keys.

func NewPostgresStore

func NewPostgresStore(exec datastore.Executor) *PostgresStore

NewPostgresStore builds the production key store.

func (*PostgresStore) Create

func (s *PostgresStore) Create(ctx context.Context, userID string, keyHash string, params CreateParams) (APIKey, error)

Create inserts a key; uuidv7() fills the ID.

func (*PostgresStore) ListForUser

func (s *PostgresStore) ListForUser(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)

ListForUser pages the keys owned by one user, newest first.

func (*PostgresStore) Renew

func (s *PostgresStore) Renew(ctx context.Context, userID string, id APIKeyID, keyHash string, expiresAt time.Time) (APIKey, error)

Renew rotates the token hash and expiry of an expired key.

func (*PostgresStore) Revoke

func (s *PostgresStore) Revoke(ctx context.Context, userID string, id APIKeyID) error

Revoke removes one key owned by the user.

func (*PostgresStore) ValidByHash

func (s *PostgresStore) ValidByHash(ctx context.Context, keyHash string) (APIKey, user.User, error)

ValidByHash resolves an unexpired key by hash, atomically bumping last_used_at in the same statement.

type RenewParams

type RenewParams struct {
	ExpiresAt time.Time
}

RenewParams carries the POST /api-keys/{id}/renew fields.

func (*RenewParams) Validate

func (p *RenewParams) Validate() error

Validate enforces the future-expiry constraint.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service holds the API key business rules and HTTP surface. Guards are not stored: the mount call receives the route groups, and the self surface reads the principal from the request context.

func NewService

func NewService(store Store, recorder identity.Recorder, opts ...ServiceOption) *Service

NewService builds the feature on the given store.

func (*Service) Create

func (s *Service) Create(ctx context.Context, userID string, params CreateParams) (APIKey, string, error)

Create mints a key for the current user and returns it with the one-time token.

func (*Service) List

func (s *Service) List(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)

List returns the caller's keys with pagination.

func (*Service) Name

func (s *Service) Name() string

Name names the feature for logs.

func (*Service) RPCService added in v0.0.12

func (s *Service) RPCService() (string, http.Handler)

RPCService returns the Connect registration for the API key surface: the procedure prefix and the handler. The surface is scoped to the caller — the same contract as the REST routes — so the composition root wraps it with the RPC authentication middleware. Minting and renewing demand a session principal: a machine credential must not extend itself.

func (*Service) Renew

func (s *Service) Renew(ctx context.Context, userID string, id APIKeyID, params RenewParams) (APIKey, string, error)

Renew rotates an expired key and returns the new one-time token.

func (*Service) Revoke

func (s *Service) Revoke(ctx context.Context, userID string, id APIKeyID) error

Revoke deletes one of the caller's keys.

func (*Service) Verify

func (s *Service) Verify(ctx context.Context, rawKey string) (kernel.Principal, error)

Verify resolves an X-API-KEY value to a principal for the transport middleware. Disabled users are rejected here.

type ServiceOption

type ServiceOption func(*Service)

ServiceOption configures the API key feature.

type Store

type Store interface {
	Create(ctx context.Context, userID string, keyHash string, params CreateParams) (APIKey, error)
	ListForUser(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)
	Revoke(ctx context.Context, userID string, id APIKeyID) error
	// Renew rotates the token hash and expiry; allowed only when
	// the key is already expired.
	Renew(ctx context.Context, userID string, id APIKeyID, keyHash string, expiresAt time.Time) (APIKey, error)
	// ValidByHash resolves a hash to the owning user, atomically
	// bumping last_used_at (UPDATE ... RETURNING).
	ValidByHash(ctx context.Context, keyHash string) (APIKey, user.User, error)
}

Store abstracts API key persistence.

Jump to

Keyboard shortcuts

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