This guide walks you through installing Keysmith, creating an API key, validating it, and setting up policies. By the end you will have a working program that exercises the core key management lifecycle.
Prerequisites01
Go 1.24+ (the module uses
go 1.25.7but any recent version works)A Go module (
go mod init)
Install02
go get github.com/xraph/keysmithThis pulls in the root module and all sub-packages (key, policy, scope, usage, rotation, plugin, store/memory, etc.).
Step 1 -- Create a store03
Every Keysmith operation needs a store backend. Start with the in-memory store for development and testing.
import "github.com/xraph/keysmith/store/memory"
store := memory.New()The memory.Store implements the full store.Store composite interface -- keys, policies, scopes, usage, and rotation -- all in-process with no external dependencies.
Step 2 -- Create the engine04
The keysmith.Engine is the central coordinator. It connects a store, a hasher, a key generator, and an optional rate limiter.
import "github.com/xraph/keysmith"
eng, err := keysmith.NewEngine(keysmith.WithStore(store))
if err != nil {
log.Fatal(err)
}Step 3 -- Set the tenant context05
Keysmith uses context.Context to carry tenant scope across all operations. Use the WithTenant helper to inject app ID and tenant ID.
ctx := keysmith.WithTenant(context.Background(), "my-app", "tenant-1")Or if using the Forge framework, scope is extracted automatically from forge.Scope.
Step 4 -- Create an API key06
import "github.com/xraph/keysmith/key"
result, err := eng.CreateKey(ctx, &keysmith.CreateKeyInput{
Name: "Production Key",
Prefix: "sk",
Environment: key.EnvLive,
Scopes: []string{"read:users", "write:users"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println("API Key:", result.RawKey)
// Output: API Key: sk_live_a3f8b2c9e1d4...
// Save this key — it will never be shown again.The raw key is returned exactly once. Only the SHA-256 hash is stored in the database.
Step 5 -- Validate a key07
When a request comes in with an API key, validate it against the store.
vr, err := eng.ValidateKey(ctx, result.RawKey)
if err != nil {
log.Fatal("invalid key:", err)
}
fmt.Println("Key ID:", vr.Key.ID)
fmt.Println("Tenant:", vr.Key.TenantID)
fmt.Println("State:", vr.Key.State)
fmt.Println("Scopes:", vr.Scopes)
// Output:
// Key ID: akey_01h2xce...
// Tenant: tenant-1
// State: active
// Scopes: [read:users write:users]Step 6 -- Rotate a key08
Rotate a key with a grace period. Both old and new keys will validate during the grace window.
import "github.com/xraph/keysmith/rotation"
newResult, err := eng.RotateKey(ctx,
vr.Key.ID,
rotation.ReasonScheduled,
24*time.Hour, // grace period
)
if err != nil {
log.Fatal(err)
}
fmt.Println("New Key:", newResult.RawKey)
// The old key remains valid for 24 hours.Step 7 -- Switch to PostgreSQL09
When you are ready for production, swap the memory store for PostgreSQL. The API does not change.
import "github.com/xraph/keysmith/store/postgres"
pgStore, err := postgres.NewFromDSN(ctx, "postgres://user:pass@localhost:5432/mydb")
if err != nil {
log.Fatal(err)
}
defer pgStore.Close()
// Run embedded migrations to create all Keysmith tables.
if err := pgStore.Migrate(ctx); err != nil {
log.Fatal(err)
}
// Use pgStore everywhere you previously used memory.New().
eng, _ := keysmith.NewEngine(keysmith.WithStore(pgStore))Next steps10
Architecture -- Understand the package dependency graph and request flow.
Entities -- Learn about the core data types (Key, Policy, Scope, Usage, Rotation).
Multi-tenancy -- How context-based tenant isolation works across all subsystems.
Plugins -- Extend Keysmith with audit trails, metrics, and Warden authorization sync.
REST API -- Mount the full API key management REST API via Forge.