Drop-in authentication library for Go SaaS apps
Find a file
Ash cd205c3626 Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores
Features:
- API key generation with configurable prefix and SHA-256 hash storage
- JWT auth (HS256, RS256) with refresh token flow and revocation
- Multi-tenant org → project → key hierarchy
- net/http middleware: RequireAPIKey, RequireJWT, RequireScope
- Rate limiting per key
- MemoryStore (tests) and SQLiteStore (production)
- Full test suite with adversarial tests and benchmarks
2026-02-19 14:48:32 +00:00
auth.go Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
auth_test.go Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
bench_test.go Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
go.mod Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
go.sum Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
jwt.go Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
middleware.go Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
README.md Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
store_memory.go Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00
store_sqlite.go Initial release: API key auth, JWT, multi-tenant, middleware, memory+SQLite stores 2026-02-19 14:48:32 +00:00

forge-auth

Drop-in authentication library for Go SaaS apps. Zero framework dependencies — works with net/http.

Features

  • API Key Auth — Generate keys with configurable prefix, SHA-256 hash storage, validation, rotation, rate limiting
  • JWT Auth — HS256/RS256, refresh token flow, token revocation via blacklist
  • Multi-tenant — Organization → Project → API Key hierarchy with scoped permissions
  • MiddlewareRequireAPIKey, RequireJWT, RequireScope for net/http
  • Pluggable StorageKeyStore interface with SQLite and in-memory implementations

Quick Start

package main

import (
    "fmt"
    "net/http"
    "time"

    auth "go.ashforge.dev/auth"
)

func main() {
    store := auth.NewMemoryStore()

    // Create org and project.
    store.CreateOrg(nil, &auth.Organization{
        ID: "org-1", Name: "My Org", CreatedAt: time.Now(),
    })
    store.CreateProject(nil, &auth.Project{
        ID: "proj-1", OrgID: "org-1", Name: "My Project", CreatedAt: time.Now(),
    })

    // Generate an API key.
    plaintext, key, _ := auth.GenerateAPIKey("at_", "my-key", "org-1", "proj-1", []string{"read", "write"})
    store.CreateKey(nil, key)
    fmt.Println("API Key (save this!):", plaintext)

    // Protected endpoint.
    mux := http.NewServeMux()
    mux.Handle("/api/data", auth.RequireAPIKey(store, auth.WithRateLimit(100, time.Minute))(
        auth.RequireScope("read")(
            http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                k := auth.GetKey(r.Context())
                fmt.Fprintf(w, "Hello %s from org %s", k.Name, k.OrgID)
            }),
        ),
    ))

    http.ListenAndServe(":8080", mux)
}

JWT Usage

cfg := &auth.JWTConfig{
    Algorithm:     auth.HS256,
    HMACSecret:    []byte("your-secret-key"),
    Issuer:        "myapp",
    DefaultExpiry: 15 * time.Minute,
    Store:         store, // For revocation support
}

// Issue token.
token, _ := auth.IssueJWT(cfg, &auth.Claims{
    Subject: "user-123",
    OrgID:   "org-1",
    Scopes:  []string{"read", "write"},
})

// Validate token.
claims, _ := auth.ValidateJWT(ctx, cfg, token)

// Revoke token.
auth.RevokeJWT(ctx, cfg, token)

// Refresh token flow.
pair, _ := auth.IssueTokenPair(&auth.RefreshTokenConfig{
    JWTConfig:     cfg,
    RefreshExpiry: 7 * 24 * time.Hour,
}, &auth.Claims{Subject: "user-123"})

Storage

Implements KeyStore interface. Ships with:

  • NewMemoryStore() — in-memory, great for tests
  • NewSQLiteStore(db) — SQLite, great for single-node production

License

MIT