Documentation
¶
Overview ¶
Package auth provides authentication and authorization for the stash server.
It supports two authentication methods:
- Session-based authentication for web UI (username/password login)
- Token-based authentication for API (X-Auth-Token header or Authorization: Bearer)
Token types:
- Named tokens with specific ACL permissions
- Public token (token="*") allowing unauthenticated access with limited permissions
Authorization uses prefix-based ACL where permissions are granted per key prefix with access levels: read (r), write (w), or read-write (rw). Wildcards (*) match any key, and longest prefix match wins. Secrets paths require explicit grant.
Configuration is loaded from a YAML file with optional hot-reload support. Sessions are stored persistently and survive server restarts.
Index ¶
- func ExtractToken(r *http.Request) string
- func MaskToken(token string) string
- type Config
- type ConfigValidator
- type PermissionConfig
- type Service
- func (s *Service) Activate(ctx context.Context) error
- func (s *Service) CheckUserPermission(username, key string, needWrite bool) bool
- func (s *Service) CreateSession(ctx context.Context, username string) (string, error)
- func (s *Service) Enabled() bool
- func (s *Service) FilterKeysForRequest(r *http.Request, keys []string) []string
- func (s *Service) FilterUserKeys(username string, keys []string) []string
- func (s *Service) GetRequestActor(r *http.Request) (actorType, actorName string)
- func (s *Service) GetSessionUser(ctx context.Context, token string) (string, bool)
- func (s *Service) InvalidateSession(ctx context.Context, token string)
- func (s *Service) IsAdmin(username string) bool
- func (s *Service) IsRequestAdmin(r *http.Request) bool
- func (s *Service) IsValidUser(username, password string) bool
- func (s *Service) LoginTTL() time.Duration
- func (s *Service) Reload(ctx context.Context) error
- func (s *Service) SessionMiddleware(loginURL string) func(http.Handler) http.Handler
- func (s *Service) TokenMiddleware(next http.Handler) http.Handler
- func (s *Service) UserCanWrite(username string) bool
- type SessionStore
- type TokenACL
- type TokenConfig
- type User
- type UserConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExtractToken ¶
ExtractToken extracts API token from request headers. Checks X-Auth-Token header first, then Authorization: Bearer header. Returns the token string (may be empty if not found).
Types ¶
type Config ¶
type Config struct {
Users []UserConfig `yaml:"users,omitempty" json:"users,omitempty" jsonschema:"description=users for web UI auth"`
Tokens []TokenConfig `yaml:"tokens,omitempty" json:"tokens,omitempty" jsonschema:"description=API tokens"`
}
Config represents the auth configuration file (stash-auth.yml).
func LoadConfig ¶
func LoadConfig(path string, validator ConfigValidator) (*Config, error)
LoadConfig reads and parses the auth YAML file. If validator is provided, the config is validated against the schema.
type ConfigValidator ¶
ConfigValidator validates auth configuration data against a schema.
type PermissionConfig ¶
type PermissionConfig struct {
Prefix string `yaml:"prefix" json:"prefix" jsonschema:"required"`
Access string `yaml:"access" json:"access" jsonschema:"required,enum=r,enum=read,enum=w,enum=write,enum=rw,enum=readwrite,enum=read-write"`
}
PermissionConfig represents a prefix-permission pair in the config file.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service handles authentication and authorization.
func New ¶
func New(authFile string, loginTTL time.Duration, hotReload bool, sessionStore SessionStore, validator ConfigValidator) (*Service, error)
New creates a new Service instance from configuration file. Returns nil if authFile is empty (authentication disabled). sessionStore is required for persistent session storage. hotReload enables watching the config file for changes.
func (*Service) Activate ¶
Activate starts auth background tasks: file watcher (if hot-reload enabled) and session cleanup. Should be called once after New(), typically from main.go.
func (*Service) CheckUserPermission ¶
CheckUserPermission checks if a user has the required permission for a key. Returns true when auth is disabled (permissive by default).
func (*Service) CreateSession ¶
CreateSession generates a new session token for the given username.
func (*Service) FilterKeysForRequest ¶
FilterKeysForRequest filters keys based on the request's authentication. Determines actor type (token, session user, or public) and filters accordingly. Returns all keys when auth is disabled.
func (*Service) FilterUserKeys ¶
FilterUserKeys filters keys based on user's read permissions. Returns all keys when auth is disabled (permissive by default).
func (*Service) GetRequestActor ¶
GetRequestActor returns the actor type and name from the request. Returns ("user", username), ("token", masked_token), or ("public", "").
func (*Service) GetSessionUser ¶
GetSessionUser returns the username for a valid session. Returns empty string and false if session is invalid or expired. Note: expiration is checked in store.GetSession, which returns ErrNotFound for expired sessions.
func (*Service) InvalidateSession ¶
InvalidateSession removes a session.
func (*Service) IsAdmin ¶
IsAdmin returns true if user has admin privileges. Returns false when auth is disabled.
func (*Service) IsRequestAdmin ¶
IsRequestAdmin checks if the request is from an admin (user or token). Returns false when auth is disabled.
func (*Service) IsValidUser ¶
IsValidUser checks if username/password are valid credentials. Uses constant-time comparison to prevent username enumeration via timing attacks.
func (*Service) Reload ¶
Reload reloads the auth configuration from the file. Validates new config before applying. On success, invalidates sessions only for users that were removed or had their password changed. On error, keeps the existing config and returns the error.
func (*Service) SessionMiddleware ¶
SessionMiddleware returns middleware that requires a valid session cookie. Used for web UI routes. Redirects to loginURL if not authenticated. For HTMX requests, uses HX-Redirect header to trigger full page navigation.
func (*Service) TokenMiddleware ¶
TokenMiddleware returns middleware that requires a valid token with appropriate permissions. Accepts X-Auth-Token header or Authorization: Bearer <token>. Used for API routes. Returns 401/403 if not authorized. Public access (token="*") is checked first and allows unauthenticated requests. For list operations (empty key), only validates token existence, filtering happens in handler.
func (*Service) UserCanWrite ¶
UserCanWrite returns true if user has any write permission. Returns true when auth is disabled (permissive by default).
type SessionStore ¶
type SessionStore interface {
CreateSession(ctx context.Context, token, username string, expiresAt time.Time) error
GetSession(ctx context.Context, token string) (username string, expiresAt time.Time, err error)
DeleteSession(ctx context.Context, token string) error
DeleteAllSessions(ctx context.Context) error
DeleteSessionsByUsername(ctx context.Context, username string) error
DeleteExpiredSessions(ctx context.Context) (int64, error)
}
SessionStore is the interface for persistent session storage.
type TokenACL ¶
type TokenACL struct {
Token string
Admin bool // grants admin privileges (audit access)
// contains filtered or unexported fields
}
TokenACL defines access control for an API token.
func (TokenACL) CheckKeyPermission ¶
CheckKeyPermission checks if this ACL grants permission for a key. For secret keys (containing "secrets" path segment), the matching prefix must also explicitly contain "secrets" - wildcards like "*" or "app/*" do not grant access to secrets.
type TokenConfig ¶
type TokenConfig struct {
Token string `yaml:"token" json:"token" jsonschema:"required"`
Admin bool `yaml:"admin,omitempty" json:"admin,omitempty" jsonschema:"description=grants admin privileges (audit access)"`
Permissions []PermissionConfig `yaml:"permissions,omitempty" json:"permissions,omitempty"`
}
TokenConfig represents an API token in the auth config file.
type User ¶
type User struct {
Name string
PasswordHash string
Admin bool // grants admin privileges (audit access)
ACL TokenACL // reuse ACL structure for permissions
}
User represents an authenticated user with ACL.
type UserConfig ¶
type UserConfig struct {
Name string `yaml:"name" json:"name" jsonschema:"required"`
Password string `yaml:"password" json:"password" jsonschema:"required"` // bcrypt hash
Admin bool `yaml:"admin,omitempty" json:"admin,omitempty" jsonschema:"description=grants admin privileges (audit access)"`
Permissions []PermissionConfig `yaml:"permissions,omitempty" json:"permissions,omitempty"`
}
UserConfig represents a user in the auth config file.