localiam

package
v1.0.1 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const ProviderLocalIAM = "localiam"

ProviderLocalIAM is the identity.Principal.Provider value set when a principal is resolved from a local IAM session.

View Source
const SessionCookieName = "midas_session"

SessionCookieName is the HTTP cookie name used to carry the session ID.

Variables

View Source
var (
	ErrInvalidCredentials = errors.New("localiam: invalid username or password")
	ErrUserDisabled       = errors.New("localiam: user account is disabled")
	ErrUserNotFound       = errors.New("localiam: user not found")
	ErrSessionNotFound    = errors.New("localiam: session not found or expired")
	ErrWeakPassword       = errors.New("localiam: password does not meet requirements")
)

Sentinel errors returned by Service methods.

Functions

func EnforceMustChangePassword

func EnforceMustChangePassword(next http.Handler) http.Handler

EnforceMustChangePassword is middleware that blocks requests from principals whose must_change_password flag is true, returning HTTP 403, unless the request path is one of the explicitly allowed paths:

  • GET /auth/me
  • POST /auth/change-password
  • POST /auth/logout

func MustChangePasswordFromContext

func MustChangePasswordFromContext(ctx context.Context) bool

MustChangePasswordFromContext retrieves the must_change_password flag. Returns false when not set (i.e. no session, or session resolved without flag).

func UserToPrincipal

func UserToPrincipal(u *User) *identity.Principal

UserToPrincipal converts a local IAM User to an *identity.Principal. The Principal.ID is prefixed with "localiam:" to namespace it from other provider namespaces (e.g. "static:", "entra:").

func WithMustChangePassword

func WithMustChangePassword(ctx context.Context, v bool) context.Context

WithMustChangePassword stores the must_change_password flag in ctx. Called by the session auth middleware after resolving a user.

Types

type Config

type Config struct {
	// Enabled controls whether local IAM is active. When false, the service
	// should not be constructed.
	Enabled bool
	// SessionTTL is how long a session remains valid. Defaults to 8 hours.
	SessionTTL time.Duration
	// SecureCookies sets the Secure flag on session cookies. Enable in
	// production (HTTPS). Disable only for local HTTP development.
	SecureCookies bool
}

Config holds localiam runtime configuration.

type Service

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

Service provides local platform IAM operations: bootstrap, login, logout, session resolution, and password management. It is the only component that touches the user and session repositories.

func NewService

func NewService(users UserRepository, sessions SessionRepository, cfg Config) *Service

NewService constructs a Service. sessionTTL defaults to 8 hours when zero.

func (*Service) AuthMiddleware

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

AuthMiddleware returns middleware that reads the session cookie, resolves the session, and stores both the principal (via platformauth.WithPrincipal) and the must_change_password flag in the request context.

It is extraction-only: it never writes an error response when the session is absent or invalid. Enforcement is the responsibility of platformauth.RequireAuthenticated, platformauth.RequireRole, and EnforceMustChangePassword.

func (*Service) Bootstrap

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

Bootstrap creates the default admin user if no users exist. It is safe to call on every startup — it is a no-op when at least one user already exists.

func (*Service) ChangePassword

func (s *Service) ChangePassword(ctx context.Context, userID, currentPassword, newPassword string) error

ChangePassword verifies currentPassword, then replaces the hash with a bcrypt hash of newPassword and clears MustChangePassword.

Password policy:

  • newPassword must not be empty
  • newPassword must not equal the literal string "admin"

func (*Service) ClearSessionCookie

func (s *Service) ClearSessionCookie(w http.ResponseWriter)

ClearSessionCookie is the exported variant used by the logout handler.

func (*Service) CreateExternalSession

func (s *Service) CreateExternalSession(ctx context.Context, p *identity.Principal) (*Session, error)

CreateExternalSession creates a session for an externally-authenticated principal (e.g. OIDC). No local user record is required. The principal is stored as JSON in the session and is decoded on each ResolveSession call. Callers must validate and normalize the principal before calling this.

func (*Service) Login

func (s *Service) Login(ctx context.Context, username, password string) (*Session, *User, error)

Login validates credentials, creates a session, and returns the session and user. Returns ErrInvalidCredentials on bad username or password.

func (*Service) Logout

func (s *Service) Logout(ctx context.Context, sessionID string) error

Logout deletes the session identified by sessionID.

func (*Service) ResolveSession

func (s *Service) ResolveSession(ctx context.Context, sessionID string) (*Session, *identity.Principal, bool, error)

ResolveSession looks up a session by ID and returns the associated session, the resolved principal, and whether the user must change their password. Returns ErrSessionNotFound when the session is absent or expired.

For external-auth sessions (OIDC) where PrincipalJSON is populated, the principal is decoded from JSON and no local user lookup is performed. mustChangePassword is always false for external sessions.

func (*Service) SetSessionCookie

func (s *Service) SetSessionCookie(w http.ResponseWriter, sessionID string, expiresAt time.Time)

SetSessionCookie writes the session cookie to the response.

type Session

type Session struct {
	ID        string
	UserID    string
	CreatedAt time.Time
	ExpiresAt time.Time
	// PrincipalJSON holds a JSON-encoded *identity.Principal for sessions
	// created by external auth providers (e.g. OIDC). When set, UserID is
	// empty and no local user record is required. Ignored for local IAM sessions.
	PrincipalJSON string
}

Session is a server-side platform IAM session. Sessions are stored server-side and identified by a cryptographically secure random ID transmitted via an HTTP-only cookie. No JWT or refresh tokens.

type SessionAuthenticator

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

SessionAuthenticator implements auth.Authenticator by resolving the session cookie to an *identity.Principal. This is the bridge that allows the platformauth middleware to use localiam sessions with the existing auth.Authenticator abstraction.

func NewSessionAuthenticator

func NewSessionAuthenticator(service *Service) *SessionAuthenticator

NewSessionAuthenticator wraps a Service as an auth.Authenticator.

func (*SessionAuthenticator) Authenticate

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

Authenticate reads the session cookie from the request and resolves it to a Principal. Returns auth.ErrNoCredentials when no cookie is present.

type SessionRepository

type SessionRepository interface {
	// Create stores a new session.
	Create(ctx context.Context, s *Session) error
	// FindByID returns nil, nil when not found.
	FindByID(ctx context.Context, id string) (*Session, error)
	// Delete removes a single session (logout).
	Delete(ctx context.Context, id string) error
	// DeleteExpired removes all sessions whose ExpiresAt is before now.
	// Called opportunistically; failures are non-fatal.
	DeleteExpired(ctx context.Context) error
}

SessionRepository defines persistence for platform IAM sessions.

type User

type User struct {
	ID                 string
	Username           string
	PasswordHash       string // bcrypt hash; never store or log plaintext
	Roles              []string
	Enabled            bool
	MustChangePassword bool
	CreatedAt          time.Time
	UpdatedAt          time.Time
	LastLoginAt        *time.Time // nil until first successful login
}

User is a local platform IAM user. Users represent human operators and administrators of the MIDAS control plane only — they are entirely separate from runtime authority (agents, surfaces, grants).

type UserRepository

type UserRepository interface {
	// FindByID returns nil, nil when not found.
	FindByID(ctx context.Context, id string) (*User, error)
	// FindByUsername returns nil, nil when not found.
	FindByUsername(ctx context.Context, username string) (*User, error)
	// Create inserts a new user. Returns an error if the username is already taken.
	Create(ctx context.Context, u *User) error
	// Update overwrites all mutable fields for an existing user.
	Update(ctx context.Context, u *User) error
	// Count returns the total number of users in the store.
	Count(ctx context.Context) (int, error)
}

UserRepository defines persistence for local IAM users.

Jump to

Keyboard shortcuts

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