Add complete auth subsystem with OAuth 2.1 authorization server using ory/fosite, local user accounts with bcrypt password hashing, session management, and HTTP handlers for the Web UI. Components: - User store with bcrypt hashing (configurable cost, default 12), CRUD, validation (username 3-64 chars alphanumeric+underscore, password 8-72 bytes) - Session store with secure random IDs, configurable lifetime (default 24h), expiration cleanup, and per-user invalidation - OAuth client store with client_id/secret generation and bcrypt verification - Fosite storage adapter implementing CoreStorage, TokenRevocationStorage, and PKCERequestStorage backed by SQLite - OAuth provider configured with authorization code (PKCE S256 mandatory), client credentials, refresh token rotation, and token introspection - HTTP handlers: POST /auth/register, POST /auth/login, POST /auth/logout, GET /auth/me, PUT /auth/password, GET /oauth/authorize, POST /oauth/token, POST /oauth/introspect - Middleware: RequireSession (cookie), RequireBearer (access token), RequireAuth (either), RequireAdmin (role check) - Structured auth event logging (login, token issuance, session lifecycle) - Schema migration 002_auth.sql extending users, oauth_clients, oauth_tokens tables and adding sessions, oauth_authorization_codes tables - Initial admin user auto-created on first run with random password printed to stdout - All tests pass with CGO_ENABLED=0, zero external runtime dependencies Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
54 lines
1.4 KiB
Go
54 lines
1.4 KiB
Go
package auth
|
|
|
|
import "time"
|
|
|
|
// Config holds configuration for the auth subsystem.
|
|
type Config struct {
|
|
// BcryptCost is the bcrypt hashing cost. Minimum 10, default 12.
|
|
BcryptCost int
|
|
|
|
// AccessTokenTTL is the lifetime of access tokens. Default 1 hour.
|
|
AccessTokenTTL time.Duration
|
|
|
|
// RefreshTokenLifetime is the absolute lifetime of refresh tokens. Default 30 days.
|
|
RefreshTokenLifetime time.Duration
|
|
|
|
// SessionLifetime is the lifetime of Web UI sessions. Default 24 hours.
|
|
SessionLifetime time.Duration
|
|
|
|
// IssuerURL is the OAuth issuer URL (e.g., http://localhost:8080).
|
|
IssuerURL string
|
|
|
|
// DevMode allows HTTP without TLS. When true, a warning is logged.
|
|
DevMode bool
|
|
|
|
// Secret is the system secret used for HMAC signing of tokens.
|
|
// Must be at least 32 bytes.
|
|
Secret []byte
|
|
}
|
|
|
|
// DefaultConfig returns a Config with sensible defaults.
|
|
func DefaultConfig() Config {
|
|
return Config{
|
|
BcryptCost: 12,
|
|
AccessTokenTTL: 1 * time.Hour,
|
|
RefreshTokenLifetime: 30 * 24 * time.Hour,
|
|
SessionLifetime: 24 * time.Hour,
|
|
DevMode: true,
|
|
}
|
|
}
|
|
|
|
// Validate checks that the config values are within acceptable ranges.
|
|
func (c Config) Validate() error {
|
|
if c.BcryptCost < 10 {
|
|
return ErrBcryptCostTooLow
|
|
}
|
|
if c.BcryptCost > 31 {
|
|
return ErrBcryptCostTooHigh
|
|
}
|
|
if len(c.Secret) < 32 {
|
|
return ErrSecretTooShort
|
|
}
|
|
return nil
|
|
}
|