auth

package
v0.1.5 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CSRFHeader      = "X-Requested-With"
	CSRFHeaderValue = "fallbck"
)

CSRFHeader must be present on cookie-authenticated state-changing requests. Browsers cannot add custom headers cross-site, so its presence proves same-origin JS.

View Source
const (
	// SessionCookieName carries the admin browser session JWT
	SessionCookieName = "fallbck_session"
	// LoginStateCookieName carries the OIDC state/nonce between login redirect and callback
	LoginStateCookieName = "fallbck_login"

	DefaultSessionTTL = 12 * time.Hour
)
View Source
const (
	AudienceBackupTicket = "fallbck-ticket"
	AudienceAgent        = "fallbck-agent"
	AudienceSession      = "fallbck-session"
	AudienceLoginState   = "fallbck-login"
)

Audiences separate the JWT types that share the server signing secret so that a token of one kind can never be presented as another.

View Source
const APIKeyPrefix = "fbk_"

APIKeyPrefix makes keys recognisable in logs and secret scanners

View Source
const DefaultAgentTokenTTL = 365 * 24 * time.Hour

DefaultAgentTokenTTL is the lifetime of an agent bearer token unless configured otherwise

View Source
const Issuer = "fallbck-server"

Issuer is the `iss` claim on every JWT minted by the server

Variables

View Source
var (
	ErrInvalidTicket = errors.New("invalid or expired backup ticket")
	ErrInvalidToken  = errors.New("invalid or expired token")
)
View Source
var ErrAgentRevoked = errors.New("agent has been revoked")

ErrAgentRevoked is returned when an agent has been deleted or revoked

View Source
var ErrInvalidAPIKey = errors.New("invalid, expired or revoked API key")

ErrInvalidAPIKey is returned for unknown, expired or revoked API keys

View Source
var ErrNotAuthorized = errors.New("identity is not authorized to access this server")

ErrNotAuthorized is returned when an authenticated identity is not permitted to administer

Functions

func AuthorizeIdentity

func AuthorizeIdentity(cfg OIDCConfig, id *Identity) error

AuthorizeIdentity applies the allow-lists of cfg to id

func ClearLoginStateCookie

func ClearLoginStateCookie(w http.ResponseWriter, opts CookieOptions)

ClearLoginStateCookie removes the OIDC state cookie

func ClearSessionCookie

func ClearSessionCookie(w http.ResponseWriter, opts CookieOptions)

ClearSessionCookie expires the session cookie

func GenerateSecureToken

func GenerateSecureToken(length int) (rawToken string, tokenHash string, err error)

GenerateSecureToken creates a cryptographically secure random token string and its SHA256 hash

func HashToken

func HashToken(rawToken string) string

HashToken returns the hex SHA-256 hash of a raw token string

func IsAPIKey

func IsAPIKey(value string) bool

IsAPIKey reports whether a bearer value looks like an admin API key

func LookupAPIKey

func LookupAPIKey(ctx context.Context, store APIKeyStore, raw string) (*db.APIKey, error)

LookupAPIKey resolves a raw key to its record, enforcing expiry and revocation

func NewAPIKey

func NewAPIKey(name, createdBy string, expiresAt *time.Time) (raw string, key *db.APIKey, err error)

NewAPIKey generates a new raw key and its persisted record. The raw key is returned exactly once; only its hash is stored.

func NewRandomToken

func NewRandomToken() (string, error)

NewRandomToken returns a URL-safe random string for OIDC state and nonce values

func SetLoginStateCookie

func SetLoginStateCookie(w http.ResponseWriter, token string, opts CookieOptions)

SetLoginStateCookie writes the short-lived OIDC state cookie

func SetSessionCookie

func SetSessionCookie(w http.ResponseWriter, token string, expires time.Time, opts CookieOptions)

SetSessionCookie writes the session cookie

func WithAgent

func WithAgent(ctx context.Context, c *AgentClaims) context.Context

WithAgent attaches agent claims to a context

func WithPrincipal

func WithPrincipal(ctx context.Context, p *Principal) context.Context

WithPrincipal attaches a principal to a context (exported for tests and dev mode)

Types

type APIKeyStore

type APIKeyStore interface {
	CreateAPIKey(ctx context.Context, key *db.APIKey) error
	GetAPIKeyByHash(ctx context.Context, hash string) (*db.APIKey, error)
	TouchAPIKey(ctx context.Context, id uuid.UUID) error
}

APIKeyStore provides API key persistence (implemented by *db.DB)

type AdminAuth

type AdminAuth struct {
	TM   *TokenManager
	Keys APIKeyStore
	// Insecure disables authentication entirely (development only)
	Insecure bool
	// LoginPath is where unauthenticated browser requests are redirected
	LoginPath string
}

AdminAuth authenticates admin requests via session cookie or API key

func NewAdminAuth

func NewAdminAuth(tm *TokenManager, keys APIKeyStore, insecure bool) *AdminAuth

NewAdminAuth constructs the admin middleware

func (*AdminAuth) Authenticate

func (a *AdminAuth) Authenticate(r *http.Request) (*Principal, error)

Authenticate resolves the principal for a request without enforcing anything

func (*AdminAuth) RequireAdmin

func (a *AdminAuth) RequireAdmin(next http.Handler) http.Handler

RequireAdmin enforces admin authentication and CSRF protection for cookie sessions. API-style paths get a JSON 401; browser navigations are redirected to the login page.

type AgentAuth

type AgentAuth struct {
	Verifier *AgentVerifier
}

AgentAuth authenticates agent requests with the agent bearer token

func (*AgentAuth) RequireAgent

func (a *AgentAuth) RequireAgent(next http.Handler) http.Handler

RequireAgent enforces a valid, unrevoked agent token and attaches the claims

type AgentClaims

type AgentClaims struct {
	AgentID   uuid.UUID
	TaskQueue string
	Version   int
	ExpiresAt time.Time
}

AgentClaims is the authenticated identity of an agent, attached to request contexts

func AgentFrom

func AgentFrom(ctx context.Context) *AgentClaims

AgentFrom returns the authenticated agent on the context, if any

type AgentStateStore

type AgentStateStore interface {
	GetAgentAuthState(ctx context.Context, id uuid.UUID) (*db.AgentAuthState, error)
}

AgentStateStore provides the persisted revocation state of agents (implemented by *db.DB)

type AgentTokenClaims

type AgentTokenClaims struct {
	TaskQueue string `json:"tq"`
	Version   int    `json:"ver"`
	jwt.RegisteredClaims
}

AgentTokenClaims is the JWT payload of an agent bearer token. `sub` is the agent ID.

func (*AgentTokenClaims) AgentID

func (c *AgentTokenClaims) AgentID() (uuid.UUID, error)

AgentID returns the agent UUID from the subject claim

type AgentVerifier

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

AgentVerifier validates agent bearer tokens against both the signature and the database state (agent exists, not revoked, token version current). Database lookups are cached per agent for a short time so every RPC does not hit Postgres.

func NewAgentVerifier

func NewAgentVerifier(tm *TokenManager, store AgentStateStore, cacheTTL time.Duration) *AgentVerifier

NewAgentVerifier creates a verifier. cacheTTL bounds how long a revocation takes to propagate.

func (*AgentVerifier) Invalidate

func (v *AgentVerifier) Invalidate(agentID uuid.UUID)

Invalidate drops the cached state for an agent (call after revocation for immediate effect)

func (*AgentVerifier) Verify

func (v *AgentVerifier) Verify(ctx context.Context, bearer string) (*AgentClaims, error)

Verify validates a bearer token value (with or without the "Bearer " prefix)

type BackupTicketClaims

type BackupTicketClaims struct {
	JobID      uuid.UUID `json:"job_id"`
	AgentID    uuid.UUID `json:"agent_id"`
	TargetID   uuid.UUID `json:"target_id"`
	Datastore  string    `json:"datastore"`
	Namespace  string    `json:"namespace"`
	BackupType string    `json:"backup_type"` // e.g. "host"
	BackupID   string    `json:"backup_id"`   // e.g. "agent-123"
	BackupTime int64     `json:"backup_time"` // unix timestamp
	jwt.RegisteredClaims
}

BackupTicketClaims defines the claims embedded in a short-lived backup session ticket

type CookieOptions

type CookieOptions struct {
	// Secure marks cookies as HTTPS-only; enable whenever PublicURL is https
	Secure bool
}

CookieOptions controls the attributes of cookies set by the server

type Identity

type Identity struct {
	Subject string
	Email   string
	Name    string
	Groups  []string
}

Identity is an authenticated admin resolved from an OIDC ID token

type LoginStateClaims

type LoginStateClaims struct {
	State string `json:"state"`
	Nonce string `json:"nonce"`
	Next  string `json:"next,omitempty"`
	jwt.RegisteredClaims
}

LoginStateClaims protects the OIDC round trip: state must match the callback query, nonce must match the ID token, next is where to send the user afterwards.

type OIDC

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

OIDC performs the authorization-code login flow against the configured provider

func NewOIDC

func NewOIDC(ctx context.Context, cfg OIDCConfig, redirectURL string) (*OIDC, error)

NewOIDC discovers the provider and prepares the OAuth2 client. redirectURL must be PublicURL + "/auth/callback" and registered with the provider.

func (*OIDC) AuthCodeURL

func (o *OIDC) AuthCodeURL(state, nonce string) string

AuthCodeURL builds the provider login URL for a state/nonce pair

func (*OIDC) Authorize

func (o *OIDC) Authorize(id *Identity) error

Authorize applies allowed_groups / allowed_emails to an identity

func (*OIDC) Exchange

func (o *OIDC) Exchange(ctx context.Context, code, nonce string) (*Identity, error)

Exchange redeems the authorization code, verifies the ID token and its nonce, and applies the allow-lists. Returns ErrNotAuthorized when the identity is valid but not permitted.

type OIDCConfig

type OIDCConfig = config.OIDCConfig

OIDCConfig is the OpenID Connect configuration (defined in pkg/config)

type Principal

type Principal struct {
	Kind    PrincipalKind
	Subject string
	Email   string
	Name    string
}

Principal is the authenticated admin identity attached to the request context

func PrincipalFrom

func PrincipalFrom(ctx context.Context) *Principal

PrincipalFrom returns the admin principal on the context, if any

func (*Principal) Display

func (p *Principal) Display() string

Display returns a human-readable identifier for audit logs and the UI

type PrincipalKind

type PrincipalKind string

PrincipalKind distinguishes how an admin request was authenticated

const (
	PrincipalSession  PrincipalKind = "session"
	PrincipalAPIKey   PrincipalKind = "apikey"
	PrincipalInsecure PrincipalKind = "insecure"
)

type SessionClaims

type SessionClaims struct {
	Email  string   `json:"email,omitempty"`
	Name   string   `json:"name,omitempty"`
	Groups []string `json:"groups,omitempty"`
	jwt.RegisteredClaims
}

SessionClaims is the payload of an admin browser session. `sub` is the OIDC subject.

type TokenManager

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

TokenManager signs and validates every JWT the server issues (backup tickets, agent tokens, admin sessions, login state) with a single HS256 secret, separated by audience.

func NewTokenManager

func NewTokenManager(secret string) *TokenManager

NewTokenManager creates a new TokenManager with a shared signing secret

func (*TokenManager) CreateAgentToken

func (tm *TokenManager) CreateAgentToken(agentID uuid.UUID, taskQueue string, version int, ttl time.Duration) (string, time.Time, error)

CreateAgentToken mints a long-lived bearer token for an enrolled agent

func (*TokenManager) CreateBackupTicket

func (tm *TokenManager) CreateBackupTicket(claims BackupTicketClaims, ttl time.Duration) (string, error)

CreateBackupTicket generates a signed JWT ticket valid for the specified duration (e.g. 2 hours)

func (*TokenManager) CreateLoginState

func (tm *TokenManager) CreateLoginState(state, nonce, next string) (string, error)

CreateLoginState signs the OIDC state cookie payload

func (*TokenManager) CreateSession

func (tm *TokenManager) CreateSession(id *Identity, ttl time.Duration) (string, time.Time, error)

CreateSession mints a session token for an authenticated admin identity

func (*TokenManager) ValidateAgentToken

func (tm *TokenManager) ValidateAgentToken(tokenString string) (*AgentTokenClaims, error)

ValidateAgentToken verifies the signature and claims of an agent token. It does NOT consult revocation state; use AgentVerifier for that.

func (*TokenManager) ValidateBackupTicket

func (tm *TokenManager) ValidateBackupTicket(ticketString string) (*BackupTicketClaims, error)

ValidateBackupTicket parses and verifies a short-lived backup ticket

func (*TokenManager) ValidateLoginState

func (tm *TokenManager) ValidateLoginState(tokenString string) (*LoginStateClaims, error)

ValidateLoginState verifies the OIDC state cookie payload

func (*TokenManager) ValidateSession

func (tm *TokenManager) ValidateSession(tokenString string) (*SessionClaims, error)

ValidateSession verifies a session token

Jump to

Keyboard shortcuts

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