systemauthsvc

package
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package systemauthsvc assembles a production-grade SystemAuth OAuth 2.0 / OpenID Connect server from configuration, for the standalone systemauth command and for host binaries that embed SystemAuth next to other applications in one process.

It owns the steps between a configuration file and a ready http.Handler:

  • LoadConfig, LoadConfigBytes: read the YAML/JSON configuration from a file or memory (with environment variable expansion), then apply overrides, defaults and validation, in that order.
  • New: enforce the production requirements (signing key, https issuer, persistent database, secure cookies) unless Options.Dev is set; open PostgreSQL ("pgx") or SQLite ("sqlite3") or use an injected *sql.DB or Ent client; optionally migrate; bootstrap the system user that owns statically configured clients; register or update those clients; and select the Ent-backed token, login session, login state and consent stores so restarts and replicas share state.
  • Service: the http.Handler plus Migrate, Ready, Close, Issuer and the discovery Metadata an in-process relying party can use without a network round trip.

Embedding SystemAuth puts its signing key in the same process (and memory) as the host's application code, and a restart of the host is a restart of the login service. See docs/systemauth/embedding.md.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotProductionReady = errors.New("systemauthsvc: refusing to start in production mode")

ErrNotProductionReady is returned by New and CheckProduction when the configuration does not meet the production requirements and Options.Dev is not set.

Functions

func CheckProduction

func CheckProduction(cfg *Config, opts Options) error

CheckProduction reports, as an error wrapping ErrNotProductionReady, every production requirement the configuration and options miss: a signing key, a public https issuer, a persistent database and secure login cookies. It returns nil when opts.Dev is set.

func Migrate

func Migrate(ctx context.Context, cfg *Config) (err error)

Migrate opens the configured database, creates or updates the schema, and closes it. Migrations are idempotent.

func NewLogger

func NewLogger(w io.Writer, level, format string) (*slog.Logger, error)

NewLogger returns a slog logger writing to w at level ("debug", "info", "warn", "error"; default info) in format ("text" or "json"; default text).

Types

type Config

type Config = systemauth.Config

Config is the SystemAuth server configuration.

func LoadConfig

func LoadConfig(path string, overrides ...Override) (*Config, error)

LoadConfig reads the configuration file at path (YAML or JSON by extension, with environment variable expansion; an empty path starts from an empty configuration), applies the overrides in order, then applies defaults and validates the result. Validation runs after the overrides, so an override can supply a value the file omits (e.g. WithDefaultIssuer).

func LoadConfigBytes

func LoadConfigBytes(data []byte, format string, overrides ...Override) (*Config, error)

LoadConfigBytes is LoadConfig for configuration already in memory, e.g. a section embedded in a host's own configuration file. format is "yaml" (or "yml") or "json"; an empty format detects JSON when the first non-space byte is '{' and YAML otherwise. Empty data starts from an empty configuration.

type Database

type Database struct {
	// Client is the Ent client.
	Client *ent.Client
	// DB is the connection pool.
	DB *sql.DB
}

Database is an Ent client with its underlying connection pool.

func OpenDatabase

func OpenDatabase(cfg *systemauth.DatabaseConfig) (*Database, error)

OpenDatabase opens the configured database without connecting: PostgreSQL through the pgx stdlib driver, SQLite through go-sqlite3, each with the matching Ent dialect.

func (*Database) Close

func (d *Database) Close() error

Close closes the Ent client and its connection pool.

type Options

type Options struct {
	// Dev relaxes the production requirements: an ephemeral signing key,
	// in-memory storage, an http issuer and insecure login cookies are
	// allowed. Never set it for a deployment that serves real users.
	Dev bool

	// Logger receives server logs. Default: slog.Default().
	Logger *slog.Logger

	// SigningKey supplies the RSA signing key programmatically (e.g. from a
	// secret manager), taking precedence over keys.private_key_file and
	// keys.private_key_pem.
	SigningKey *rsa.PrivateKey

	// DB injects an open connection pool instead of opening
	// cfg.Database. DBDialect names its database ("postgres" or "sqlite")
	// and is required with DB. The caller owns DB; Close does
	// not close it.
	DB        *sql.DB
	DBDialect string

	// EntClient injects an Ent client for the identity schema instead of
	// opening a database. When DB is also set it is used for the readiness
	// ping. The caller owns the client; Close does not close it.
	EntClient *ent.Client

	// Migrate creates or updates the database schema before the system
	// user and static clients are written. Without it the schema must
	// already exist (run Migrate or "systemauth migrate" first).
	Migrate bool

	// ServerOptions are passed to systemauth.NewEmbedded after the storage,
	// logger and readiness options New sets, e.g. WithObservability or
	// custom social login stores.
	ServerOptions []systemauth.Option
}

Options configures New with what does not belong in the configuration file: the deployment mode, the logger, programmatic secrets and injected database handles. The issuer, database DSN, signing key file and key ID are configuration fields; set them in the file, through LoadConfig overrides, or directly on the Config.

type Override

type Override func(*Config) error

Override adjusts a loaded configuration before defaults and validation are applied, e.g. from command-line flags or environment variables.

func WithDatabase

func WithDatabase(driver, dsn string) Override

WithDatabase sets the database driver ("postgres" or "sqlite") and DSN. Environment variables in the DSN are expanded. Both must be given together; when both are empty the override does nothing.

func WithDefaultIssuer

func WithDefaultIssuer(issuer string) Override

WithDefaultIssuer sets the issuer only when the configuration has none, e.g. a localhost URL in development.

func WithDefaultSigningKeyPEM

func WithDefaultSigningKeyPEM(pem string) Override

WithDefaultSigningKeyPEM sets a PEM RSA signing key only when the configuration supplies none, e.g. from a secret injected through the environment.

func WithIssuer

func WithIssuer(issuer string) Override

WithIssuer sets the public issuer URL.

func WithKeyID

func WithKeyID(kid string) Override

WithKeyID sets the JWKS key ID ("kid"). The default is the RFC 7638 thumbprint of the signing key.

func WithSigningKeyFile

func WithSigningKeyFile(path string) Override

WithSigningKeyFile sets the PEM RSA signing key file, replacing any configured key.

type Service

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

Service is a configured SystemAuth server ready to be mounted.

func New

func New(ctx context.Context, cfg *Config, opts Options) (*Service, error)

New builds a SystemAuth server from cfg. Unless opts.Dev is set it refuses a configuration that misses a production requirement (see CheckProduction). With a database it connects, optionally migrates, bootstraps the system user that owns statically configured clients, registers or updates those clients, and keeps tokens, login sessions, login state and consent grants in the database. Without one (Dev only) everything is in memory.

func (*Service) Close

func (s *Service) Close() error

Close releases the database New opened. Injected handles (Options.DB, Options.EntClient) are left to their owner.

func (*Service) Config

func (s *Service) Config() Config

Config returns the effective configuration (defaults applied).

func (*Service) Discovery

func (s *Service) Discovery() systemauth.OpenIDConfiguration

Discovery returns the OpenID Provider configuration served at /.well-known/openid-configuration.

func (*Service) EntClient

func (s *Service) EntClient() *ent.Client

EntClient returns the Ent client, or nil with in-memory storage.

func (*Service) Handler

func (s *Service) Handler() http.Handler

Handler returns the HTTP handler serving every SystemAuth endpoint (discovery, JWKS, OAuth, UserInfo, health and, when configured, social login). Mount it at the root of the issuer's host.

func (*Service) Issuer

func (s *Service) Issuer() string

Issuer returns the public issuer URL.

func (*Service) KeyID

func (s *Service) KeyID() string

KeyID returns the JWKS key ID of the signing key.

func (*Service) Metadata

func (s *Service) Metadata() relyingparty.Metadata

Metadata returns the provider metadata a relying party needs, identical to what discovery serves. Pass it to relyingparty.NewClientWithMetadata so an in-process relying party skips the discovery request.

func (*Service) Migrate

func (s *Service) Migrate(ctx context.Context) error

Migrate creates or updates the database schema. It is idempotent and does nothing with in-memory storage.

func (*Service) Ready

func (s *Service) Ready(ctx context.Context) error

Ready runs the readiness checks behind GET /readyz (the database ping) and returns nil when the service can serve requests.

func (*Service) ServeHTTP

func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

func (*Service) Server

func (s *Service) Server() *systemauth.Server

Server returns the underlying SystemAuth server.

func (*Service) StorageName

func (s *Service) StorageName() string

StorageName names the storage backend: the database driver or dialect, "ent" for an injected client, or "in-memory".

Jump to

Keyboard shortcuts

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