apikey

package
v0.0.9 Latest Latest
Warning

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

Go to latest
Published: Jan 3, 2026 License: Apache-2.0 Imports: 27 Imported by: 0

README

API Key Plugin

Enterprise-grade API key authentication plugin for external client access to your AuthSome application. Provides secure, multi-tenant API key management with rate limiting, scope-based permissions, and comprehensive audit trails.

Features

  • Multi-Tenant Support: API keys scoped to organizations
  • Secure Storage: Keys hashed with SHA-256, never stored in plaintext
  • Flexible Authentication: Multiple extraction methods (header, query param)
  • Granular Permissions: Scope and permission-based access control
  • Rate Limiting: Per-key rate limits with configurable windows
  • Usage Tracking: Comprehensive analytics and audit trails
  • Key Lifecycle: Create, rotate, update, deactivate, delete operations
  • Automatic Expiration: Optional key expiration with cleanup
  • IP Whitelisting: Restrict keys to specific IP addresses (optional)
  • Webhook Notifications: Alert on key events (optional)

Installation

import (
    "github.com/xraph/authsome"
    apikeyPlugin "github.com/xraph/authsome/plugins/apikey"
)

// Initialize AuthSome
auth := authsome.New(db)

// Add API Key plugin
apikey := apikeyPlugin.NewPlugin()
auth.Use(apikey)

Configuration

Configure via YAML or environment variables:

auth:
  apikey:
    # Service configuration
    default_rate_limit: 1000      # Default requests per hour
    max_rate_limit: 10000          # Maximum allowed rate limit
    default_expiry: 8760h          # Default expiration (1 year)
    max_keys_per_user: 10          # Maximum keys per user
    max_keys_per_org: 100          # Maximum keys per organization
    key_length: 32                 # Key byte length
    
    # Authentication options
    allow_query_param: false       # Allow ?api_key=xxx (not recommended)
    
    # Rate limiting
    rate_limiting:
      enabled: true
      window: 1h                   # Rate limit time window
    
    # IP whitelisting (optional)
    ip_whitelisting:
      enabled: false
      strict_mode: false
    
    # Webhook notifications (optional)
    webhooks:
      enabled: false
      notify_on_created: true
      notify_on_rotated: true
      notify_on_deleted: true
      notify_on_rate_limit: true
      notify_on_expiring: true
      expiry_warning_days: 7
      webhook_urls:
        - "https://your-webhook-url.com/api/events"

Usage

Creating API Keys
// In your handler or service
req := &apikey.CreateAPIKeyRequest{
    OrgID:       "org_abc123",
    UserID:      "user_xyz789",
    Name:        "Production API Key",
    Description: "Key for production server",
    Scopes:      []string{"users:read", "users:write"},
    Permissions: map[string]string{
        "resources:read": "all",
        "resources:write": "own",
    },
    RateLimit:   5000, // 5000 requests per hour
    ExpiresAt:   &expiryDate,
    Metadata: map[string]string{
        "environment": "production",
        "server": "api-01",
    },
}

apiKey, err := apikeyService.CreateAPIKey(ctx, req)
// apiKey.Key contains the full key: "ak_abc123_xyz789.secret_token"
// Store this securely - it won't be shown again!
Protecting Routes with API Keys
Method 1: Global Middleware (Optional Authentication)
// Apply to all routes - sets context if valid key present
router.Use(apikey.Middleware())

// Routes will have API key context if provided
router.GET("/api/v1/users", handler.ListUsers)
Method 2: Required Authentication
// Require valid API key for specific routes
apiGroup := router.Group("/api/v1")
apiGroup.Use(apikey.RequireAPIKey()) // Any valid API key

apiGroup.GET("/users", handler.ListUsers)
apiGroup.POST("/users", handler.CreateUser)
Method 3: Scope-Based Authentication
// Require specific scopes
router.GET("/api/v1/users", handler.ListUsers).
    Use(apikey.RequireAPIKey("users:read"))

router.POST("/api/v1/users", handler.CreateUser).
    Use(apikey.RequireAPIKey("users:write"))

router.DELETE("/api/v1/users/:id", handler.DeleteUser).
    Use(apikey.RequireAPIKey("users:delete", "admin"))
Method 4: Permission-Based Authentication
router.POST("/api/v1/admin/settings", handler.UpdateSettings).
    Use(apikey.RequirePermission("admin:settings:write"))
Extracting API Key Information in Handlers
import apikeyPlugin "github.com/xraph/authsome/plugins/apikey"

func (h *Handler) ListUsers(c forge.Context) error {
    // Check if authenticated via API key
    if !apikeyPlugin.IsAuthenticated(c) {
        return c.JSON(401, map[string]string{
            "error": "Authentication required",
        })
    }
    
    // Get API key details
    apiKey := apikeyPlugin.GetAPIKey(c)
    orgID := apikeyPlugin.GetOrgID(c)
    user := apikeyPlugin.GetUser(c)
    scopes := apikeyPlugin.GetScopes(c)
    
    // Use organization ID for multi-tenant queries
    users, err := h.userService.ListByOrganization(ctx, orgID, limit, offset)
    
    return c.JSON(200, users)
}
Client Usage

Clients can authenticate using any of these methods:

curl -H "Authorization: ApiKey ak_abc123_xyz789.secret_token" \
     https://api.example.com/api/v1/users
Method 2: Bearer Token Format
curl -H "Authorization: Bearer ak_abc123_xyz789.secret_token" \
     https://api.example.com/api/v1/users
Method 3: Custom Header
curl -H "X-API-Key: ak_abc123_xyz789.secret_token" \
     https://api.example.com/api/v1/users
Method 4: Query Parameter (If Enabled)
curl https://api.example.com/api/v1/users?api_key=ak_abc123_xyz789.secret_token

⚠️ Note: Query parameter method is disabled by default and not recommended for production use.

Key Management Operations

Rotate API Key
req := &apikey.RotateAPIKeyRequest{
    ID:     "key_id_123",
    OrgID:  "org_abc123",
    UserID: "user_xyz789",
}

newKey, err := apikeyService.RotateAPIKey(ctx, req)
// Old key is deactivated, new key is created with same settings
Update API Key
active := false
req := &apikey.UpdateAPIKeyRequest{
    Name:   ptr("Updated Key Name"),
    Scopes: []string{"users:read"}, // Reduced permissions
    Active: &active, // Deactivate key
}

updated, err := apikeyService.UpdateAPIKey(ctx, keyID, userID, orgID, req)
Delete API Key
err := apikeyService.DeleteAPIKey(ctx, keyID, userID, orgID)
// Soft delete - key remains in database for audit
Cleanup Expired Keys
// Run periodically (e.g., daily cron job)
count, err := apikeyService.CleanupExpired(ctx)
// Returns number of keys cleaned up

Multi-Tenancy

API keys are automatically scoped to organizations. When authenticated via API key:

  • Organization context is automatically injected
  • User belongs to the key's organization
  • All queries should respect organization boundaries
func (h *Handler) GetResource(c forge.Context) error {
    // Organization ID is automatically available
    orgID := apikeyPlugin.GetOrgID(c)
    
    // Multi-tenant decorators will respect this organization
    resource, err := h.service.FindByID(ctx, resourceID)
    // Service automatically filters by orgID from context
    
    return c.JSON(200, resource)
}

Security Best Practices

✅ DO:
  1. Store keys securely - Use secrets managers (HashiCorp Vault, AWS Secrets Manager)
  2. Use HTTPS only - Never transmit keys over unencrypted connections
  3. Rotate regularly - Implement key rotation policies (e.g., every 90 days)
  4. Minimal scopes - Grant only required permissions
  5. Monitor usage - Track and alert on suspicious activity
  6. Set expiration - Use time-limited keys when possible
  7. Use IP whitelisting - Restrict server-to-server keys to known IPs
  8. Rate limiting - Protect against abuse
❌ DON'T:
  1. Don't commit keys - Never check keys into version control
  2. Don't share keys - One key per application/server
  3. Don't use in browsers - API keys are for server-to-server communication
  4. Don't log keys - Sanitize logs to prevent key exposure
  5. Don't use query params - Prefer headers for key transmission
  6. Don't ignore expiration - Clean up unused keys

Rate Limiting

Per-key rate limits are enforced automatically:

// Keys have individual rate limits
apiKey.RateLimit = 5000 // 5000 requests per window

// Rate limit window configured globally
config.RateLimiting.Window = time.Hour // 1 hour window

// Exceeded limit returns 429 Too Many Requests
{
  "error": "rate limit exceeded",
  "message": "API key rate limit of 5000 requests per window exceeded"
}

Error Codes

HTTP Status Error Code Description
401 MISSING_API_KEY No API key provided
401 INVALID_API_KEY Key not found or invalid
401 KEY_EXPIRED API key has expired
401 KEY_DEACTIVATED API key has been deactivated
403 INSUFFICIENT_SCOPE Missing required scope
403 INSUFFICIENT_PERMISSION Missing required permission
429 RATE_LIMIT_EXCEEDED Rate limit exceeded

Monitoring & Analytics

Usage Tracking

Each API key tracks:

  • Total request count
  • Last used timestamp
  • Last used IP address
  • Last used user agent
apiKey, _ := apikeyService.GetAPIKey(ctx, keyID, userID, orgID)
fmt.Printf("Used %d times, last at %v from %s",
    apiKey.UsageCount,
    apiKey.LastUsedAt,
    apiKey.LastUsedIP,
)
Audit Logs

All key operations are logged via the audit service:

  • api_key.created
  • api_key.updated
  • api_key.rotated
  • api_key.deleted

Testing

Mock Mode
// For development/testing
config := apikey.DefaultConfig()
config.AllowQueryParam = true // Allow query params in dev

// Create test keys
testKey, _ := service.CreateAPIKey(ctx, &apikey.CreateAPIKeyRequest{
    OrgID:  "test_org",
    UserID: "test_user",
    Name:   "Test Key",
    Scopes: []string{"*"}, // All permissions
})
Integration Tests
func TestAPIKeyAuth(t *testing.T) {
    // Create test key
    key, err := service.CreateAPIKey(ctx, req)
    require.NoError(t, err)
    
    // Make authenticated request
    resp := httptest.NewRecorder()
    req := httptest.NewRequest("GET", "/api/v1/users", nil)
    req.Header.Set("Authorization", "ApiKey "+key.Key)
    
    router.ServeHTTP(resp, req)
    assert.Equal(t, 200, resp.Code)
}

Migration from Other Auth Methods

From Session-Based Auth

API keys complement session-based auth - use both:

// Session auth for web UI
router.Group("/dashboard").Use(sessionAuth.Middleware())

// API key auth for external APIs
router.Group("/api/v1").Use(apikey.RequireAPIKey())
From JWT

API keys are simpler for server-to-server:

// JWT for mobile apps (user authentication)
router.Group("/mobile/v1").Use(jwt.Middleware())

// API keys for server integrations
router.Group("/api/v1").Use(apikey.RequireAPIKey())

Advanced Features

IP Whitelisting
// Coming soon - restrict keys to specific IPs
apiKey.AllowedIPs = []string{"203.0.113.0/24", "198.51.100.42"}
Webhook Notifications
// Coming soon - notify on key events
config.Webhooks.Enabled = true
config.Webhooks.WebhookURLs = []string{"https://hooks.slack.com/..."}
Hierarchical Scopes
// Coming soon - scope inheritance
"admin:*"       → all admin scopes
"users:*"       → users:read, users:write, users:delete
"resources:read" → read-only access

Troubleshooting

Key Not Working
  1. Check key format: ak_<prefix>.<secret>
  2. Verify key is active: apiKey.Active == true
  3. Check expiration: apiKey.ExpiresAt
  4. Verify scopes match requirements
  5. Check rate limits haven't been exceeded
Rate Limit Issues
# Check current usage
curl -H "Authorization: ApiKey $API_KEY" \
     https://api.example.com/api-keys/$KEY_ID?user_id=$USER&org_id=$ORG

# Response includes usage_count and rate_limit
Organization Context Missing

Ensure multi-tenancy plugin is loaded before API key plugin:

auth.Use(multitenancy.NewPlugin())
auth.Use(apikey.NewPlugin())

Support

For issues, questions, or feature requests:

License

Part of AuthSome - See LICENSE file in repository root.

Documentation

Index

Examples

Constants

View Source
const (
	APIKeyContextKey       contextKey = "api_key"
	APIKeyUserContextKey   contextKey = "api_key_user"
	APIKeyAuthenticatedKey contextKey = "api_key_authenticated"
	APIKeyPermissionsKey   contextKey = "api_key_permissions"
)

Variables

This section is empty.

Functions

func GetAPIKey

func GetAPIKey(c forge.Context) *apikey.APIKey

GetAPIKey extracts the API key from the request context

func GetOrgID

func GetOrgID(c forge.Context) string

GetOrgID extracts the organization ID from context (V2 architecture) Returns the xid.ID, check with IsNil() before use

func GetScopes

func GetScopes(c forge.Context) []string

GetScopes returns the scopes associated with the authenticated API key

func GetUser

func GetUser(c forge.Context) *user.User

GetUser extracts the user associated with the API key from context

func IsAuthenticated

func IsAuthenticated(c forge.Context) bool

IsAuthenticated checks if the request is authenticated via API key

Types

type AssignRoleRequest added in v0.0.7

type AssignRoleRequest struct {
	ID     string `path:"id" validate:"required"`
	RoleID string `json:"roleID" validate:"required"`
}

type AutoCleanupConfig

type AutoCleanupConfig struct {
	Enabled  bool          `json:"enabled" yaml:"enabled"`
	Interval time.Duration `json:"interval" yaml:"interval"` // How often to run cleanup
}

AutoCleanupConfig configures automatic cleanup of expired keys

type Config

type Config struct {
	// Service configuration
	DefaultRateLimit int           `json:"default_rate_limit" yaml:"default_rate_limit"`
	MaxRateLimit     int           `json:"max_rate_limit" yaml:"max_rate_limit"`
	DefaultExpiry    time.Duration `json:"default_expiry" yaml:"default_expiry"`
	MaxKeysPerUser   int           `json:"max_keys_per_user" yaml:"max_keys_per_user"`
	MaxKeysPerOrg    int           `json:"max_keys_per_org" yaml:"max_keys_per_org"`
	KeyLength        int           `json:"key_length" yaml:"key_length"`

	// Authentication configuration
	AllowQueryParam bool `json:"allow_query_param" yaml:"allow_query_param"` // Allow API key in query params (not recommended for production)

	// Rate limiting configuration
	RateLimiting RateLimitConfig `json:"rate_limiting" yaml:"rate_limiting"`

	// IP whitelisting
	IPWhitelisting IPWhitelistConfig `json:"ip_whitelisting" yaml:"ip_whitelisting"`

	// Webhook notifications
	Webhooks WebhookConfig `json:"webhooks" yaml:"webhooks"`

	// Cleanup scheduler
	AutoCleanup AutoCleanupConfig `json:"auto_cleanup" yaml:"auto_cleanup"`
}

Config holds the API key plugin configuration

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default configuration

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the configuration

type CreateAPIKeyRequest added in v0.0.7

type CreateAPIKeyRequest struct {
	Name        string            `json:"name" validate:"required"`
	Description string            `json:"description"`
	Scopes      []string          `json:"scopes" validate:"required,min=1"`
	Permissions map[string]string `json:"permissions"`
	RateLimit   int               `json:"rate_limit"`
	AllowedIPs  []string          `json:"allowed_ips"`
	Metadata    map[string]string `json:"metadata"`
}

Request types

type CreateAPIKeyResponse

type CreateAPIKeyResponse struct {
	APIKey  *apikey.APIKey `json:"api_key"`
	Message string         `json:"message"`
}

Response types

type DashboardExtension added in v0.0.2

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

DashboardExtension implements the ui.DashboardExtension interface This allows the API key plugin to add its own screens to the dashboard

func NewDashboardExtension added in v0.0.2

func NewDashboardExtension(plugin *Plugin) *DashboardExtension

NewDashboardExtension creates a new dashboard extension for API keys

func (*DashboardExtension) CreateAPIKey added in v0.0.2

func (e *DashboardExtension) CreateAPIKey(c forge.Context) error

CreateAPIKey handles API key creation

func (*DashboardExtension) DashboardWidgets added in v0.0.2

func (e *DashboardExtension) DashboardWidgets() []ui.DashboardWidget

DashboardWidgets returns widgets to show on the main dashboard

func (*DashboardExtension) ExtensionID added in v0.0.2

func (e *DashboardExtension) ExtensionID() string

ExtensionID returns the unique identifier for this extension

func (*DashboardExtension) NavigationItems added in v0.0.2

func (e *DashboardExtension) NavigationItems() []ui.NavigationItem

NavigationItems returns navigation items to register (none for settings-only plugin)

func (*DashboardExtension) RenderDashboardWidget added in v0.0.2

func (e *DashboardExtension) RenderDashboardWidget(basePath string, currentApp *app.App) g.Node

RenderDashboardWidget renders the API key stats widget

func (*DashboardExtension) RevokeAPIKey added in v0.0.2

func (e *DashboardExtension) RevokeAPIKey(c forge.Context) error

RevokeAPIKey handles API key revocation

func (*DashboardExtension) RotateAPIKey added in v0.0.2

func (e *DashboardExtension) RotateAPIKey(c forge.Context) error

RotateAPIKey handles API key rotation

func (*DashboardExtension) Routes added in v0.0.2

func (e *DashboardExtension) Routes() []ui.Route

Routes returns routes to register under /dashboard/app/:appId/

func (*DashboardExtension) ServeAPIKeysConfigPage added in v0.0.2

func (e *DashboardExtension) ServeAPIKeysConfigPage(c forge.Context) error

ServeAPIKeysConfigPage renders the configuration page

func (*DashboardExtension) ServeAPIKeysListPage added in v0.0.2

func (e *DashboardExtension) ServeAPIKeysListPage(c forge.Context) error

ServeAPIKeysListPage renders the API keys management page

func (*DashboardExtension) ServeAPIKeysSecurityPage added in v0.0.2

func (e *DashboardExtension) ServeAPIKeysSecurityPage(c forge.Context) error

ServeAPIKeysSecurityPage renders the security settings page

func (*DashboardExtension) SetRegistry added in v0.0.2

func (e *DashboardExtension) SetRegistry(registry *dashboard.ExtensionRegistry)

SetRegistry sets the extension registry reference (called by dashboard after registration)

func (*DashboardExtension) SettingsPages added in v0.0.2

func (e *DashboardExtension) SettingsPages() []ui.SettingsPage

SettingsPages returns full settings pages for the sidebar layout

func (*DashboardExtension) SettingsSections added in v0.0.2

func (e *DashboardExtension) SettingsSections() []ui.SettingsSection

SettingsSections returns settings sections (deprecated, using SettingsPages instead)

func (*DashboardExtension) UpdateConfig added in v0.0.2

func (e *DashboardExtension) UpdateConfig(c forge.Context) error

UpdateConfig handles configuration updates

func (*DashboardExtension) UpdateSecurity added in v0.0.2

func (e *DashboardExtension) UpdateSecurity(c forge.Context) error

UpdateSecurity handles security settings updates

type DeleteAPIKeyRequest added in v0.0.7

type DeleteAPIKeyRequest struct {
	ID string `path:"id" validate:"required"`
}

type GetAPIKeyRequest added in v0.0.7

type GetAPIKeyRequest struct {
	ID string `path:"id" validate:"required"`
}

type GetEffectivePermissionsRequest added in v0.0.7

type GetEffectivePermissionsRequest struct {
	ID string `path:"id" validate:"required"`
}

type GetRolesRequest added in v0.0.7

type GetRolesRequest struct {
	ID string `path:"id" validate:"required"`
}

type Handler

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

Handler handles API key related HTTP requests Updated for V2 architecture: App → Environment → Organization

func NewHandler

func NewHandler(service *apikey.Service, config Config) *Handler

NewHandler creates a new API key handler

func (*Handler) AssignRole

func (h *Handler) AssignRole(c forge.Context) error

AssignRole handles POST /api-keys/:id/roles

func (*Handler) CreateAPIKey

func (h *Handler) CreateAPIKey(c forge.Context) error

CreateAPIKey handles POST /api-keys

func (*Handler) DeleteAPIKey

func (h *Handler) DeleteAPIKey(c forge.Context) error

DeleteAPIKey handles DELETE /api-keys/:id

func (*Handler) GetAPIKey

func (h *Handler) GetAPIKey(c forge.Context) error

GetAPIKey handles GET /api-keys/:id

func (*Handler) GetEffectivePermissions

func (h *Handler) GetEffectivePermissions(c forge.Context) error

GetEffectivePermissions handles GET /api-keys/:id/permissions

func (*Handler) GetRoles

func (h *Handler) GetRoles(c forge.Context) error

GetRoles handles GET /api-keys/:id/roles

func (*Handler) ListAPIKeys

func (h *Handler) ListAPIKeys(c forge.Context) error

ListAPIKeys handles GET /api-keys

func (*Handler) RotateAPIKey

func (h *Handler) RotateAPIKey(c forge.Context) error

RotateAPIKey handles POST /api-keys/:id/rotate

func (*Handler) UnassignRole

func (h *Handler) UnassignRole(c forge.Context) error

UnassignRole handles DELETE /api-keys/:id/roles/:roleId

func (*Handler) UpdateAPIKey

func (h *Handler) UpdateAPIKey(c forge.Context) error

UpdateAPIKey handles PATCH /api-keys/:id

func (*Handler) VerifyAPIKey

func (h *Handler) VerifyAPIKey(c forge.Context) error

VerifyAPIKey handles POST /api-keys/verify

type IPWhitelistConfig

type IPWhitelistConfig struct {
	Enabled    bool `json:"enabled" yaml:"enabled"`
	StrictMode bool `json:"strict_mode" yaml:"strict_mode"` // Reject if IP not in allowlist
}

IPWhitelistConfig configures IP whitelisting

type KeyStats added in v0.0.2

type KeyStats struct {
	TotalActive     int
	UsedLast24h     int
	AvgRequestRate  float64
	ExpiringSoon    int
	TotalRevoked    int
	MostUsedKeyName string
}

KeyStats holds API key statistics

type ListAPIKeysRequest added in v0.0.7

type ListAPIKeysRequest struct {
	Page   int   `query:"page"`
	Limit  int   `query:"limit"`
	Active *bool `query:"active"`
}

type MessageResponse

type MessageResponse = responses.MessageResponse

Use shared response type

type Middleware

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

Middleware handles API key authentication

func NewMiddleware

func NewMiddleware(
	service *apikey.Service,
	userSvc *user.Service,
	rateLimiter *ratelimit.Service,
	config Config,
) *Middleware

NewMiddleware creates a new API key middleware

func (*Middleware) Authenticate

func (m *Middleware) Authenticate(next func(forge.Context) error) func(forge.Context) error

Authenticate attempts to authenticate using an API key from the request This middleware is non-blocking - it will set context values if a valid API key is found, but will not reject requests without API keys (use RequireAPIKey for that)

func (*Middleware) RequireAPIKey

func (m *Middleware) RequireAPIKey(scopes ...string) func(next func(forge.Context) error) func(forge.Context) error

RequireAPIKey enforces API key authentication

func (*Middleware) RequirePermission

func (m *Middleware) RequirePermission(permissions ...string) func(next func(forge.Context) error) func(forge.Context) error

RequirePermission enforces specific permissions

type Plugin

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

Plugin implements API key authentication for external clients

Example (Basic)

Example: Basic plugin registration

package main

import (
	"context"

	"github.com/uptrace/bun"
	"github.com/xraph/authsome"

	apikeyPlugin "github.com/xraph/authsome/plugins/apikey"
	"github.com/xraph/forge"
)

func main() {
	// Initialize database (example)
	var db *bun.DB // Your database connection

	// Create Forge app
	app := forge.New()

	// Create AuthSome instance
	auth := authsome.New(
		authsome.WithDatabase(db),
		authsome.WithForgeApp(app),
	)

	// Register API key plugin
	plugin := apikeyPlugin.NewPlugin()
	_ = auth.RegisterPlugin(plugin)

	// Initialize (this will call plugin Init)
	_ = auth.Initialize(context.Background())

	// Mount to router
	_ = auth.Mount(app.Router(), "/api/auth")

	// Now API key authentication is available
}
Example (CreateKey)

Example: Create and use API keys programmatically

package main

import (
	"context"

	"github.com/rs/xid"
	"github.com/xraph/authsome/core/apikey"
)

func main() {
	var ctx context.Context
	var service *apikey.Service // From plugin.Service()

	// V2 Architecture: App → Environment → Organization (optional)
	appID := xid.New()  // Platform app (required)
	envID := xid.New()  // Environment: dev/staging/prod (required)
	orgID := xid.New()  // User org (optional - can be nil)
	userID := xid.New() // User creating the key

	// Create an API key
	req := &apikey.CreateAPIKeyRequest{
		AppID:         appID,  // Platform app (required)
		EnvironmentID: envID,  // Environment (required)
		OrgID:         &orgID, // User-created org (optional)
		UserID:        userID, // User who owns the key
		Name:          "Production API Key",
		Description:   "Key for prod server",
		KeyType:       apikey.KeyTypeSecret, // sk (secret), pk (publishable), rk (restricted)
		Scopes:        []string{"users:read", "users:write"},
		RateLimit:     5000,
	}

	key, err := service.CreateAPIKey(ctx, req)
	if err != nil {
		panic(err)
	}

	// IMPORTANT: Store key.Key securely - it won't be shown again!
	// key.Key = "sk_prod_abc123.secret_token"

	_ = key
}
Example (ProtectRoutes)

Example: Protect routes with API key middleware

package main

import (
	apikeyPlugin "github.com/xraph/authsome/plugins/apikey"
	"github.com/xraph/forge"
)

func main() {
	// This example demonstrates how to extract API key context from requests
	// For actual middleware setup, see the plugin documentation

	// When a request is authenticated with an API key, you can extract context:

	// In your handler:
	handler := func(c forge.Context) error {
		// Extract API key context (V2 Architecture)
		key := apikeyPlugin.GetAPIKey(c)                 // The full API key data
		orgID := apikeyPlugin.GetOrgID(c)                // User org ID (may be empty string)
		user := apikeyPlugin.GetUser(c)                  // Associated user
		scopes := apikeyPlugin.GetScopes(c)              // API key scopes
		authenticated := apikeyPlugin.IsAuthenticated(c) // Check if authenticated

		// V2 Architecture context is available in the key:
		if key != nil {
			_ = key.AppID          // Platform app ID
			_ = key.EnvironmentID  // Environment ID (dev/staging/prod)
			_ = key.OrganizationID // User-created org ID (may be nil)
			_ = key.Scopes         // Key scopes
			_ = key.Permissions    // Key permissions
		}

		_ = orgID
		_ = user
		_ = scopes
		_ = authenticated

		return c.JSON(200, map[string]string{"status": "ok"})
	}

	_ = handler

	// Middleware is configured through the plugin's Middleware() method
	// See plugin documentation for setup details
}

func NewPlugin

func NewPlugin(opts ...PluginOption) *Plugin

NewPlugin creates a new API key plugin instance with optional configuration

func (*Plugin) DashboardExtension added in v0.0.2

func (p *Plugin) DashboardExtension() ui.DashboardExtension

DashboardExtension returns the dashboard extension for this plugin This implements the PluginWithDashboardExtension interface

func (*Plugin) ID

func (p *Plugin) ID() string

ID returns the plugin identifier

func (*Plugin) Init

func (p *Plugin) Init(authInstance core.Authsome) error

Init initializes the plugin with dependencies

func (*Plugin) Middleware

func (p *Plugin) Middleware() func(next func(forge.Context) error) func(forge.Context) error

Middleware returns the authentication middleware

func (*Plugin) Migrate

func (p *Plugin) Migrate() error

Migrate runs plugin migrations

func (*Plugin) RegisterHooks

func (p *Plugin) RegisterHooks(hookRegistry *hooks.HookRegistry) error

RegisterHooks registers plugin hooks with the hook registry

func (*Plugin) RegisterRoutes

func (p *Plugin) RegisterRoutes(router forge.Router) error

RegisterRoutes registers the plugin's HTTP routes

func (*Plugin) RegisterServiceDecorators

func (p *Plugin) RegisterServiceDecorators(services *registry.ServiceRegistry) error

RegisterServiceDecorators allows plugins to replace core services with decorated versions

func (*Plugin) RequireAPIKey

func (p *Plugin) RequireAPIKey(scopes ...string) func(next func(forge.Context) error) func(forge.Context) error

RequireAPIKey returns middleware that requires a valid API key

func (*Plugin) RequirePermission

func (p *Plugin) RequirePermission(permissions ...string) func(next func(forge.Context) error) func(forge.Context) error

RequirePermission returns middleware that requires specific permissions

func (*Plugin) Service

func (p *Plugin) Service() *apikey.Service

Service returns the API key service for direct access

func (*Plugin) StopCleanupScheduler

func (p *Plugin) StopCleanupScheduler()

StopCleanupScheduler stops the cleanup scheduler (for graceful shutdown)

type PluginOption

type PluginOption func(*Plugin)

PluginOption is a functional option for configuring the API key plugin

func WithAllowQueryParam

func WithAllowQueryParam(allow bool) PluginOption

WithAllowQueryParam sets whether to allow API keys in query params

func WithAutoCleanup

func WithAutoCleanup(enabled bool, interval time.Duration) PluginOption

WithAutoCleanup sets the auto cleanup configuration

func WithDefaultConfig

func WithDefaultConfig(cfg Config) PluginOption

WithDefaultConfig sets the default configuration for the plugin

func WithDefaultExpiry

func WithDefaultExpiry(expiry time.Duration) PluginOption

WithDefaultExpiry sets the default key expiry

func WithDefaultRateLimit

func WithDefaultRateLimit(limit int) PluginOption

WithDefaultRateLimit sets the default rate limit

func WithKeyLength

func WithKeyLength(length int) PluginOption

WithKeyLength sets the API key length

func WithMaxKeysPerOrg

func WithMaxKeysPerOrg(max int) PluginOption

WithMaxKeysPerOrg sets the maximum keys per organization

func WithMaxKeysPerUser

func WithMaxKeysPerUser(max int) PluginOption

WithMaxKeysPerUser sets the maximum keys per user

func WithMaxRateLimit

func WithMaxRateLimit(limit int) PluginOption

WithMaxRateLimit sets the maximum rate limit

type RateLimitConfig

type RateLimitConfig struct {
	Enabled bool          `json:"enabled" yaml:"enabled"`
	Window  time.Duration `json:"window" yaml:"window"` // Time window for rate limiting
}

RateLimitConfig configures rate limiting behavior

type RolesResponse

type RolesResponse struct {
	Roles []*apikey.Role `json:"roles"`
}

type RotateAPIKeyRequest added in v0.0.7

type RotateAPIKeyRequest struct {
	ID string `path:"id" validate:"required"`
}

type RotateAPIKeyResponse

type RotateAPIKeyResponse struct {
	APIKey  *apikey.APIKey `json:"api_key"`
	Message string         `json:"message"`
}

type ScopeDefinition added in v0.0.2

type ScopeDefinition struct {
	Value       string
	Label       string
	Description string
	DangerLevel string // "safe", "moderate", "dangerous", "critical"
	Category    string // "read", "write", "admin", "special"
}

ScopeDefinition defines a scope with metadata

type UnassignRoleRequest added in v0.0.7

type UnassignRoleRequest struct {
	ID     string `path:"id" validate:"required"`
	RoleID string `path:"roleId" validate:"required"`
}

type UpdateAPIKeyRequest added in v0.0.7

type UpdateAPIKeyRequest struct {
	ID          string            `path:"id" validate:"required"`
	Name        *string           `json:"name"`
	Description *string           `json:"description"`
	Scopes      []string          `json:"scopes"`
	Permissions map[string]string `json:"permissions"`
	RateLimit   *int              `json:"rate_limit"`
	AllowedIPs  []string          `json:"allowed_ips"`
	Metadata    map[string]string `json:"metadata"`
}

type VerifyAPIKeyRequest added in v0.0.7

type VerifyAPIKeyRequest struct {
	Key string `json:"key" validate:"required"`
}

type WebhookConfig

type WebhookConfig struct {
	Enabled           bool     `json:"enabled" yaml:"enabled"`
	NotifyOnCreated   bool     `json:"notify_on_created" yaml:"notify_on_created"`
	NotifyOnRotated   bool     `json:"notify_on_rotated" yaml:"notify_on_rotated"`
	NotifyOnDeleted   bool     `json:"notify_on_deleted" yaml:"notify_on_deleted"`
	NotifyOnRateLimit bool     `json:"notify_on_rate_limit" yaml:"notify_on_rate_limit"`
	NotifyOnExpiring  bool     `json:"notify_on_expiring" yaml:"notify_on_expiring"` // Notify N days before expiry
	ExpiryWarningDays int      `json:"expiry_warning_days" yaml:"expiry_warning_days"`
	WebhookURLs       []string `json:"webhook_urls" yaml:"webhook_urls"`
}

WebhookConfig configures webhook notifications for API key events

Jump to

Keyboard shortcuts

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