Authsome

Keysmith Bridge

Centralized API key management — delegates key operations to Keysmith for rate limiting, scoping, and rotation.

The Keysmith bridge connects Authsome to the Keysmith API key management extension. When configured, all API key creation, validation, and revocation operations are delegated to Keysmith, which provides a richer feature set than Authsome's built-in API key store: rate limiting per key, scope enforcement, key rotation with grace periods, usage analytics, and multi-tenant isolation.

Interface

The bridge.KeyManager interface is defined in github.com/xraph/authsome/bridge:

type KeyManager interface {
    CreateKey(ctx context.Context, input *CreateKeyInput) (*KeyResult, error)
    ValidateKey(ctx context.Context, rawKey string) (*ValidatedKey, error)
    RevokeKey(ctx context.Context, keyID string) error
}

type CreateKeyInput struct {
    Name        string            `json:"name"`
    Owner       string            `json:"owner"`        // User ID
    Environment string            `json:"environment,omitempty"`
    Scopes      []string          `json:"scopes,omitempty"`
    Metadata    map[string]string `json:"metadata,omitempty"`
}

type KeyResult struct {
    ID     string `json:"id"`
    RawKey string `json:"raw_key"` // Only returned on creation; store securely
}

type ValidatedKey struct {
    ID          string            `json:"id"`
    Name        string            `json:"name"`
    Owner       string            `json:"owner"`
    Environment string            `json:"environment,omitempty"`
    Scopes      []string          `json:"scopes,omitempty"`
    Metadata    map[string]string `json:"metadata,omitempty"`
}

Authsome provides a first-class WithKeysmith option that accepts the concrete *keysmith.Engine directly:

import (
    "github.com/xraph/authsome"
    "github.com/xraph/keysmith"
)

// Build the Keysmith engine.
keysmithEng, err := keysmith.New(
    keysmith.WithStore(keysmithStore),
    keysmith.WithRateLimit(keysmith.RateLimitConfig{
        RequestsPerMinute: 1000,
    }),
)
if err != nil {
    log.Fatal(err)
}

// Register with Authsome using the first-class option.
eng, err := authsome.New(
    authsome.WithStore(pgStore),
    authsome.WithKeysmith(keysmithEng),
)

Internally, WithKeysmith calls:

e.keysmith_ = keysmithEng
e.keyManager = keysmithadapter.New(keysmithEng)

Setup with the generic KeyManager interface

import (
    "github.com/xraph/authsome"
    "github.com/xraph/authsome/bridge/keysmithadapter"
)

eng, err := authsome.New(
    authsome.WithStore(pgStore),
    authsome.WithKeyManager(keysmithadapter.New(keysmithEng)),
)

Capabilities gained with Keysmith

FeatureWithout KeysmithWith Keysmith
Key creationStored in authsome_api_keys tableManaged in Keysmith with full audit trail
Key validationDatabase lookup by prefixKeysmith's in-memory cache with rate limiting
Rate limitingNot availablePer-key rate limits (req/min, req/day)
Scope enforcementNot availableDeclarative scope validation
Key rotationManual revoke + createGrace period rotation (old key valid for X minutes)
Usage analyticsNot availablePer-key request counts, last-used timestamp
Multi-tenant isolationApp-level scopingFull tenant-scoped key namespacing

Scope enforcement

When Keysmith is configured, API key validation includes scope checking. Create keys with explicit scopes:

result, err := eng.CreateAPIKey(ctx, &authsome.CreateAPIKeyRequest{
    Name:   "CI pipeline key",
    UserID: userID,
    Scopes: []string{"read:users", "read:sessions"},
})

Keysmith validates that the key's declared scopes match the required scopes for each operation. Requests from keys without the required scope are rejected with a 403 Forbidden.

Standalone development stub

During development without Keysmith, API key operations return ErrKeyManagerNotAvailable:

import "github.com/xraph/authsome/bridge"

// Authsome uses NoopKeyManager internally when no KeyManager is set.
// You can also set it explicitly to be explicit:
eng, err := authsome.New(
    authsome.WithStore(memory.New()),
    authsome.WithKeyManager(bridge.NewNoopKeyManager()),
)

When NoopKeyManager is active, calls to create, validate, or revoke API keys return an error. If your application does not use API keys, this is fine — no action needed.

On this page