Help us shape the future of Go! Take the 2026 Go Developer Survey

auth

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package auth manages local and OIDC accounts, sealed Ed25519 signing keys, five-minute access cookies, thirty-day rotating refresh families and CSRF. Cookie authentication checks the persisted session on every request; password changes and disabled/deleted accounts invalidate access immediately. Refresh secrets and API tokens are persisted only as SHA-256 hashes. Access/refresh lifetimes may be configured through Options. A replay revokes the whole family. Login, refresh and authenticated logout append durable auth-resource events. Failed local logins record only validated attempted account names, never passwords or addresses; backoff/admission denials do not produce audit floods. OIDC failures are attributed only to verified, matching persisted identities. Actor identities include the persisted OIDC issuer and public token metadata, so provider identities and separate API tokens remain distinguishable.

Index

Constants

View Source
const (
	AccessCookie  = "karakoram_access"
	RefreshCookie = "karakoram_refresh"
	CSRFCookie    = "karakoram_csrf"
	CSRFHeader    = "X-Karakoram-CSRF"
)

Cookie names and CSRFHeader are shared with HTTP clients.

Variables

View Source
var ErrCSRF = errors.New("invalid CSRF token")

ErrCSRF indicates a missing or mismatched double-submit token.

View Source
var ErrInvalid = errors.New("invalid authentication input")

ErrInvalid identifies malformed account, password, token or OIDC input.

View Source
var ErrPasswordChangeRequired = errors.New("password change required")

ErrPasswordChangeRequired restricts sessions pending a mandatory change.

View Source
var ErrRateLimited = errors.New("login temporarily locked")

ErrRateLimited indicates exponential login backoff is active.

View Source
var ErrUnauthenticated = errors.New("invalid credentials or expired authentication")

ErrUnauthenticated deliberately does not disclose account existence.

Functions

func CloneRestrictions added in v0.3.0

func CloneRestrictions(r *domain.TokenRestrictions) *domain.TokenRestrictions

CloneRestrictions takes an independent authentication snapshot.

func HashPassword

func HashPassword(password string) (string, error)

HashPassword uses Argon2id v19, 64 MiB, three iterations, two lanes, a random 16-byte salt and a 32-byte output. Passwords require 12 Unicode characters and are bounded to 1024 bytes to avoid unbounded input processing.

func IsMCPTraffic added in v0.3.0

func IsMCPTraffic(ctx context.Context) bool

IsMCPTraffic reports whether this is a trusted MCP-to-REST dispatch.

func NormalizeRestrictions added in v0.3.0

func NormalizeRestrictions(r *domain.TokenRestrictions) (*domain.TokenRestrictions, error)

NormalizeRestrictions validates names and the generated permission vocabulary.

func RestrictionAllows added in v0.3.0

func RestrictionAllows(r *domain.TokenRestrictions, resource, action, object string) bool

RestrictionAllows evaluates the deny overlay; nil preserves legacy authority.

func RestrictionAllowsOperation added in v0.3.0

func RestrictionAllowsOperation(r *domain.TokenRestrictions, resource, action, object string, collection, secret bool) bool

RestrictionAllowsOperation checks collections without granting global-object access.

func RestrictionsSubset added in v0.3.0

func RestrictionsSubset(child, parent *domain.TokenRestrictions) bool

RestrictionsSubset rejects any child overlay that could widen the parent's authority.

func ValidatePassword

func ValidatePassword(password string) error

ValidatePassword enforces the shared local-password policy without hashing.

func VerifyPassword

func VerifyPassword(encoded, password string) bool

VerifyPassword checks a bounded supported PHC encoding with constant-time comparison. Parameters from an untrusted hash cannot increase memory or work.

func WithClientIP

func WithClientIP(ctx context.Context, ip string) context.Context

WithClientIP attaches the direct peer address to a login context. Forwarded headers must only be used by callers with an explicit trusted-proxy policy.

func WithMCPTraffic added in v0.3.0

func WithMCPTraffic(ctx context.Context) context.Context

WithMCPTraffic marks a trusted in-process REST dispatch. Network headers cannot set this marker. OAuth authentication may accept MCP-audience tokens only when IsMCPTraffic is true; verified client hosts may later refine the audit suffix.

Types

type OIDCSettings

type OIDCSettings struct {
	IssuerURL     string   `json:"issuerURL"`
	ClientID      string   `json:"clientID"`
	ClientSecret  string   `json:"clientSecret,omitempty"`
	Scopes        []string `json:"scopes"`
	GroupsClaim   string   `json:"groupsClaim"`
	UsernameClaim string   `json:"usernameClaim"`
	AllowedGroups []string `json:"allowedGroups,omitempty"`
	AutoCreate    bool     `json:"autoCreate"`
}

OIDCSettings configures server-side authorization-code SSO. ClientSecret is write-only: empty on update retains it, and Settings always omits its value.

type Options

type Options struct {
	Store                 *store.Store
	Sealer                *secrets.Sealer
	Issuer                string
	AccessTTL, RefreshTTL time.Duration
	SecureCookies         bool
	PublicURL             string
	Logger                *slog.Logger
}

Options configures persisted authentication and externally visible URLs.

type Principal

type Principal struct {
	Account            string
	AccountCreatedAt   time.Time
	Subjects           []string
	Via                string
	MustChangePassword bool
	TokenID            string
	TokenName          string
	OIDCIssuer         string
	CSRFToken          string
	Restrictions       *domain.TokenRestrictions
}

Principal is the authenticated identity used by policy enforcement.

func (Principal) Actor

func (p Principal) Actor() string

Actor returns the persisted account identity scoped to its OIDC issuer, distinguishing API tokens by public name and ID without credential material.

type RateLimitError

type RateLimitError struct {
	RetryAfterSeconds int
}

RateLimitError carries a secret-independent retry delay for login admission.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

func (*RateLimitError) Unwrap

func (e *RateLimitError) Unwrap() error

type Service

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

Service owns signing keys and serializes identity/session lifecycle changes.

func New

func New(o Options) (*Service, error)

New loads the sealed persistent signing key or generates one on first start.

func (*Service) Authenticate

func (s *Service) Authenticate(r *http.Request) (*Principal, error)

Authenticate accepts a bearer API token, otherwise validates access cookies, persisted session state, account lifecycle and CSRF on unsafe methods.

func (*Service) Bootstrap

func (s *Service) Bootstrap(ctx context.Context, password string) (string, error)

Bootstrap creates the initial administrator once and returns only a generated password. Supplied passwords are never returned; every initial admin must change.

func (*Service) ChangePassword

func (s *Service) ChangePassword(ctx context.Context, name, old, password string) error

ChangePassword requires the current local password and invalidates old tokens.

func (*Service) CreateAccount

func (s *Service) CreateAccount(ctx context.Context, a domain.Account, password string) (*domain.Account, error)

CreateAccount creates a local-password identity; OIDC identities are only provisioned by verified callbacks.

func (*Service) CreateToken

func (s *Service) CreateToken(ctx context.Context, owner, name string, expires *time.Time, restrictions *domain.TokenRestrictions) (string, domain.ApiToken, error)

CreateToken issues a kk_-prefixed secret exactly once.

func (*Service) DeleteAccount

func (s *Service) DeleteAccount(ctx context.Context, name string) error

DeleteAccount removes the owner and all of its persisted sessions and tokens. The account is removed first so partial cleanup still fails authentication closed.

func (*Service) DeleteToken

func (s *Service) DeleteToken(ctx context.Context, id string) error

DeleteToken revokes an API token immediately.

func (*Service) GetAccount

func (s *Service) GetAccount(ctx context.Context, name string) (*domain.Account, error)

GetAccount returns a credential-free account.

func (*Service) GetToken

func (s *Service) GetToken(ctx context.Context, id string) (*domain.ApiToken, error)

GetToken returns token metadata without its hash.

func (*Service) ListAccounts

func (s *Service) ListAccounts(ctx context.Context) ([]domain.Account, error)

ListAccounts returns accounts without credentials or provider identity keys.

func (*Service) ListTokens

func (s *Service) ListTokens(ctx context.Context, owner string) ([]domain.ApiToken, error)

ListTokens returns metadata, optionally restricted to one owner.

func (*Service) Login

func (s *Service) Login(ctx context.Context, w http.ResponseWriter, user, password string) (*SessionInfo, error)

Login applies account+IP exponential backoff and issues the local session. After five failures delay starts at one second and doubles to fifteen minutes.

func (*Service) LoginHTTP

func (s *Service) LoginHTTP(w http.ResponseWriter, r *http.Request, user, password string) (*SessionInfo, error)

LoginHTTP derives the rate-limit address from RemoteAddr, never proxy headers.

func (*Service) Logout

func (s *Service) Logout(ctx context.Context, w http.ResponseWriter, r *http.Request) error

Logout revokes the refresh family and clears all three local cookies.

func (*Service) OIDCCallbackHandler

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

OIDCCallbackHandler verifies signature, issuer, audience, expiry, nonce and provider subject before provisioning. Existing local identities cannot be adopted by an OIDC issuer, even if their username matches.

func (*Service) OIDCLoginHandler

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

OIDCLoginHandler sends state, nonce and S256 PKCE to the verified issuer. The signed ten-minute state cookie uses Lax only for the top-level SSO callback; local access/refresh/CSRF cookies remain SameSite Strict.

func (*Service) RecoverAdmin

func (s *Service) RecoverAdmin(ctx context.Context, name, password, masterKey string) (bool, error)

RecoverAdmin applies operator-supplied local administrator recovery before the server accepts traffic. An empty password disables recovery; an empty name selects admin. The master key derives a domain-separated fingerprint key, so the persisted receipt cannot be used to guess passwords without that key.

The singleton server must be the only writer. The receipt is written last: after an interrupted application the next startup repeats the recovery, never treating partially recovered credentials, policy or revocations as complete. Errors must abort startup. No recovery secret is logged or recorded in events.

func (*Service) Refresh

func (s *Service) Refresh(ctx context.Context, w http.ResponseWriter, r *http.Request) (*SessionInfo, error)

Refresh consumes a token once, keeping its hash as a durable replay receipt. Family expiry is absolute rather than extended indefinitely by rotation.

func (*Service) ResetPassword

func (s *Service) ResetPassword(ctx context.Context, name, password string) error

ResetPassword supports offline administrative recovery and forces a change.

func (*Service) Settings

func (s *Service) Settings(ctx context.Context) (*OIDCSettings, error)

Settings reads one persisted snapshot without joining identity mutations. Public version discovery must remain available while a mutation waits to write.

func (*Service) UpdateAccount

func (s *Service) UpdateAccount(ctx context.Context, a domain.Account) (*domain.Account, error)

UpdateAccount updates display name, roles, disabled and must-change flags.

func (*Service) UpdateSettings

func (s *Service) UpdateSettings(ctx context.Context, cfg OIDCSettings) error

UpdateSettings validates and seals write-only OIDC credentials at rest.

func (*Service) UpdateToken

func (s *Service) UpdateToken(ctx context.Context, t domain.ApiToken) (*domain.ApiToken, error)

UpdateToken changes display name and expiry, never ownership or secret.

type SessionInfo

type SessionInfo struct {
	Account   domain.Account `json:"account"`
	CSRFToken string         `json:"csrfToken"`
	ExpiresAt time.Time      `json:"expiresAt"`
}

SessionInfo is returned with newly issued cookies and includes the CSRF token.

Jump to

Keyboard shortcuts

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