Documentation
¶
Overview ¶
Package auth handles authentication and session tickets.
Package auth provides local accounts, platform sessions, CSRF, and WebSocket tickets. OIDC is behind an interface from day one (implementation later).
Index ¶
- Constants
- Variables
- func CheckWSOrigin(r *http.Request, allowed []string) bool
- func ClearSessionCookie(w http.ResponseWriter)
- func HashPassword(password string) (string, error)
- func SetSessionCookie(w http.ResponseWriter, s Session, secure bool)
- func VerifyPassword(encoded, password string) (bool, error)
- type Authenticator
- type LocalAuthenticator
- type MFAVerifier
- type OIDCAuthenticator
- type Session
- type SessionManager
- func (m *SessionManager) Create(userID string, sessionVersion ...int) Session
- func (m *SessionManager) CreateMFAChallenge(userID string) (string, time.Time)
- func (m *SessionManager) Destroy(tokenString string)
- func (m *SessionManager) Get(tokenString string) (Session, bool)
- func (m *SessionManager) ParseMFAChallenge(tokenString string) (string, bool)
- type TicketScope
- type TicketStore
Constants ¶
const ( // SessionCookieName carries the signed stateless browser session JWT. SessionCookieName = "shellcn_session" // CSRFHeader is where state-changing HTTP requests echo the CSRF token. CSRFHeader = "X-CSRF-Token" // DefaultSessionTTL is how long a platform session lives. DefaultSessionTTL = 24 * time.Hour // MFAChallengeTTL bounds how long a password-verified user has to complete the // second factor before they must sign in again. MFAChallengeTTL = 5 * time.Minute )
const DefaultTicketTTL = 30 * time.Second
DefaultTicketTTL is the short lifetime of a WS ticket.
Variables ¶
var ( // ErrInvalidCredentials is returned for a bad username/password pair. ErrInvalidCredentials = errors.New("auth: invalid credentials") // ErrAccountDisabled is returned when the account exists but is disabled. ErrAccountDisabled = errors.New("auth: account disabled") // ErrNotImplemented is returned by an authenticator that is not yet available. ErrNotImplemented = errors.New("auth: not implemented") )
var ErrInvalidHash = errors.New("auth: invalid password hash")
ErrInvalidHash is returned when a stored password hash is malformed.
var ErrTicketInvalid = errors.New("auth: invalid ticket")
ErrTicketInvalid is returned for any ticket failure (unknown, expired, used, or scope mismatch) — deliberately undifferentiated so it leaks nothing.
Functions ¶
func CheckWSOrigin ¶
CheckWSOrigin reports whether the request's Origin header is same-site with the Host (or matches an explicit allowlist). A missing Origin is rejected for cross-origin safety on the WS upgrade path.
func ClearSessionCookie ¶
func ClearSessionCookie(w http.ResponseWriter)
ClearSessionCookie expires the session cookie on logout.
func HashPassword ¶
HashPassword returns a PHC-formatted argon2id hash of password.
func SetSessionCookie ¶
func SetSessionCookie(w http.ResponseWriter, s Session, secure bool)
SetSessionCookie writes the HttpOnly, SameSite=Lax session cookie. Secure is set when the request is served over TLS.
func VerifyPassword ¶
VerifyPassword reports whether password matches the encoded argon2id hash, using a constant-time comparison.
Types ¶
type Authenticator ¶
type Authenticator interface {
Authenticate(ctx context.Context, username, password string) (models.User, error)
}
Authenticator verifies a principal and returns the authenticated user. Local accounts and OIDC implement the same interface.
type LocalAuthenticator ¶
type LocalAuthenticator struct {
// contains filtered or unexported fields
}
LocalAuthenticator verifies username/password against the user store.
func NewLocalAuthenticator ¶
func NewLocalAuthenticator(users store.UserStore) *LocalAuthenticator
func (*LocalAuthenticator) Authenticate ¶
func (a *LocalAuthenticator) Authenticate(ctx context.Context, username, password string) (models.User, error)
Authenticate looks up the user, verifies the password, and rejects disabled accounts. It returns ErrInvalidCredentials for both unknown users and wrong passwords (no user-enumeration signal).
type MFAVerifier ¶
MFAVerifier is the optional second-factor (TOTP) hook.
type OIDCAuthenticator ¶
type OIDCAuthenticator struct{}
OIDCAuthenticator holds the OIDC interface in place; it has no implementation.
func (OIDCAuthenticator) Authenticate ¶
Authenticate always reports not-implemented.
type Session ¶
type Session struct {
ID string
UserID string
CSRFToken string
SessionVersion int
ExpiresAt time.Time
}
Session is one authenticated browser session.
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager signs and verifies stateless browser session JWTs.
func NewSessionManager ¶
func NewSessionManager(ttl time.Duration) *SessionManager
NewSessionManager returns a manager with an ephemeral signing key. Production code should use NewSessionManagerWithKey so sessions survive process restarts.
func NewSessionManagerWithKey ¶
func NewSessionManagerWithKey(ttl time.Duration, key []byte) *SessionManager
NewSessionManagerWithKey returns a JWT session manager with a stable HMAC key.
func (*SessionManager) Create ¶
func (m *SessionManager) Create(userID string, sessionVersion ...int) Session
Create starts a new stateless session for userID, returning its signed JWT.
func (*SessionManager) CreateMFAChallenge ¶
func (m *SessionManager) CreateMFAChallenge(userID string) (string, time.Time)
CreateMFAChallenge issues a short-lived token proving a user passed the password step; it carries no CSRF token, so it can never be used as a session.
func (*SessionManager) Destroy ¶
func (m *SessionManager) Destroy(tokenString string)
Destroy revokes one browser session token for the remainder of its lifetime.
func (*SessionManager) Get ¶
func (m *SessionManager) Get(tokenString string) (Session, bool)
Get validates a signed session JWT.
func (*SessionManager) ParseMFAChallenge ¶
func (m *SessionManager) ParseMFAChallenge(tokenString string) (string, bool)
ParseMFAChallenge validates a challenge token and returns the pending user id.
type TicketScope ¶
type TicketScope struct {
ConnectionID string
RouteID string
Params map[string]string
UserID string
}
TicketScope binds a ticket to exactly one resource + acting user. Binding the params means a ticket minted for pod-A can't be replayed against pod-B.
type TicketStore ¶
type TicketStore struct {
// contains filtered or unexported fields
}
TicketStore mints and redeems single-use, short-lived WS tickets. Browsers can't set Authorization on a WS upgrade, so tickets are mandatory. The store is in-memory and not shared across instances.
func NewTicketStore ¶
func NewTicketStore(ttl time.Duration) *TicketStore
NewTicketStore returns a store with the given TTL (0 = default).
func (*TicketStore) Mint ¶
func (s *TicketStore) Mint(scope TicketScope) (token string, expiresAt time.Time)
Mint issues a token bound to scope, expiring after the store's TTL.
func (*TicketStore) Redeem ¶
func (s *TicketStore) Redeem(token string, want TicketScope) error
Redeem validates a token against the request's scope and consumes it (single-use). Any mismatch, expiry, or reuse returns ErrTicketInvalid.