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

auth

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Package auth provides authentication and authorization middleware for the kube-workspaces API. It implements OIDC-based login flows, JWT session management, role-based access control (admin/editor/viewer), and integrates with the AuthConfig and User CRDs for configuration. When auth is disabled, all requests are treated as admin-level access.

Package auth provides authentication and authorization middleware for the kube-workspaces API. When auth is disabled (AuthConfig.spec.enabled=false), all middleware passes through transparently.

Index

Constants

View Source
const (
	// UserContextKey is the context key for the authenticated user.
	UserContextKey contextKey = "auth-user"
	// SessionCookieName is the name of the session cookie.
	SessionCookieName = "kw-session"
)
View Source
const LocalAuthSystemNamespace = "kube-workspaces-system"

LocalAuthSystemNamespace is where local-auth password Secrets live, regardless of a user's personal namespace. Matches the controller's bootstrap-admin convention.

Variables

This section is empty.

Functions

func AuthEnabled

func AuthEnabled(ctx context.Context) bool

AuthEnabled returns true if there is a user in the context (meaning auth is active).

func ContextWithUser

func ContextWithUser(ctx context.Context, user *UserInfo) context.Context

ContextWithUser adds user info to the context.

func CreateSessionToken

func CreateSessionToken(email, displayName, role string, groups []string, signingKey []byte, expiry time.Duration) (string, error)

CreateSessionToken creates a signed session token for the given user.

func FilterNamespaces

func FilterNamespaces(ctx context.Context, namespaces []string) []string

FilterNamespaces filters a list of namespaces to only those the user has access to. If the user is nil (auth disabled) or admin, all namespaces are returned.

func FilterWorkspaces

func FilterWorkspaces(ctx context.Context, workspaces []map[string]interface{}) []map[string]interface{}

FilterWorkspaces filters workspace objects to only those in namespaces the user can access.

func GeneratePassword added in v0.3.0

func GeneratePassword() (string, error)

GeneratePassword returns a cryptographically random password suitable for bootstrap/default use, drawn from passwordCharset.

func GetPasswordHash added in v0.3.0

func GetPasswordHash(secret *unstructured.Unstructured) (string, error)

GetPasswordHash extracts the bcrypt hash from a password Secret's .data.

func HasMinimumRole

func HasMinimumRole(userRole, minRole string) bool

HasMinimumRole checks if a user role meets the minimum required role level. Role hierarchy: admin > editor > viewer.

func HashPassword added in v0.3.0

func HashPassword(password string) (string, error)

HashPassword bcrypt-hashes the given plaintext password.

func IsAdmin

func IsAdmin(ctx context.Context) bool

IsAdmin returns true if the user has admin role.

func Middleware

func Middleware(provider *ConfigProvider) func(http.Handler) http.Handler

Middleware creates an HTTP middleware that validates session tokens. When auth is disabled, all requests pass through without authentication.

func ProvisionLocalUser added in v0.3.0

func ProvisionLocalUser(ctx context.Context, provider *ConfigProvider, email, displayName, role, password string, groups []string) (string, string, error)

ProvisionLocalUser creates a User CR with local auth enabled and a password Secret. If password is empty, a random one is generated. Returns the plaintext password that was set (for one-time display to an admin), the User CR name, and any error.

func ProvisionUser

func ProvisionUser(ctx context.Context, provider *ConfigProvider, email, displayName, role string, groups []string) error

ProvisionUser creates a User CR for a new user during first login.

func RequireNamespaceAccess

func RequireNamespaceAccess(getNamespace func(*http.Request) string) func(http.Handler) http.Handler

RequireNamespaceAccess checks that the user has access to the specified namespace. Admins have access to all namespaces.

func RequireRole

func RequireRole(minRole string) func(http.Handler) http.Handler

RequireRole is an HTTP middleware that checks the user has at minimum the specified role. Role hierarchy: admin > editor > viewer.

func ResetLocalUserPassword added in v0.3.0

func ResetLocalUserPassword(ctx context.Context, provider *ConfigProvider, userName string) (string, error)

ResetLocalUserPassword generates a new random password for an existing local user, updates their password Secret, and sets mustChangePassword. Returns the new plaintext password for one-time display to an admin.

func UserHasNamespaceAccess

func UserHasNamespaceAccess(user *UserInfo, namespace string) bool

UserHasNamespaceAccess checks if a user has access to a given namespace.

func ValidatePasswordComplexity added in v0.3.0

func ValidatePasswordComplexity(password string) error

ValidatePasswordComplexity enforces a minimum password policy.

Types

type Config

type Config struct {
	Enabled       bool
	IssuerURL     string
	ClientID      string
	ClientSecret  string
	Scopes        []string
	UsernameClaim string
	GroupsClaim   string
	SigningKey    []byte
	// PreviousSigningKey is the signing key that was in use before the current
	// one. It is retained (for up to one TokenExpiry after a rotation) so that
	// sessions minted with it keep validating while key rotation settles.
	PreviousSigningKey      []byte
	TokenExpiry             time.Duration
	RefreshExpiry           time.Duration
	PersonalNamespaces      PersonalNamespacesConfig
	Registration            RegistrationConfig
	AdminEmails             []string
	RestrictNamespaceAccess bool
	LocalAuthEnabled        bool
}

Config holds the resolved authentication configuration.

func (*Config) SessionSigningKeys added in v0.4.0

func (c *Config) SessionSigningKeys() [][]byte

SessionSigningKeys returns the signing keys acceptable for validating session tokens: the current key first, followed by any rotation predecessor that is still within its acceptance window.

type ConfigProvider

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

ConfigProvider loads and caches the AuthConfig from Kubernetes.

func NewConfigProvider

func NewConfigProvider(dynamicClient dynamic.Interface) *ConfigProvider

NewConfigProvider creates a new ConfigProvider.

func (*ConfigProvider) CreatePasswordSecret added in v0.3.0

func (p *ConfigProvider) CreatePasswordSecret(ctx context.Context, name, passwordHash, plaintextPassword string) error

CreatePasswordSecret creates a new Secret holding a local user's bcrypt password hash (and, transiently, plaintext password) in LocalAuthSystemNamespace.

func (*ConfigProvider) CreateUser

CreateUser creates a new User CR.

func (*ConfigProvider) DeletePasswordSecret added in v0.3.0

func (p *ConfigProvider) DeletePasswordSecret(ctx context.Context, name string) error

DeletePasswordSecret deletes a local user's password Secret.

func (*ConfigProvider) DeleteUser

func (p *ConfigProvider) DeleteUser(ctx context.Context, name string) error

DeleteUser deletes a User CR by name.

func (*ConfigProvider) GetAuthConfig

func (p *ConfigProvider) GetAuthConfig(ctx context.Context) (*unstructured.Unstructured, error)

GetAuthConfig returns the raw AuthConfig CR.

func (*ConfigProvider) GetConfig

func (p *ConfigProvider) GetConfig(ctx context.Context) (*Config, error)

GetConfig returns the current auth configuration, fetching from Kubernetes if needed.

func (*ConfigProvider) GetPasswordSecret added in v0.3.0

func (p *ConfigProvider) GetPasswordSecret(ctx context.Context, name string) (*unstructured.Unstructured, error)

GetPasswordSecret fetches the raw Secret backing a local user's password, from LocalAuthSystemNamespace.

func (*ConfigProvider) GetUser

GetUser fetches a User CR by name.

func (*ConfigProvider) GetUserByEmail

func (p *ConfigProvider) GetUserByEmail(ctx context.Context, email string) (*unstructured.Unstructured, error)

GetUserByEmail fetches a User CR by email (list and filter).

func (*ConfigProvider) InvalidateCache

func (p *ConfigProvider) InvalidateCache()

InvalidateCache forces the config to be reloaded on next access.

func (*ConfigProvider) ListUsers

ListUsers returns all User CRs.

func (*ConfigProvider) UpdateAuthConfig

UpdateAuthConfig updates the AuthConfig CR.

func (*ConfigProvider) UpdatePasswordHash added in v0.3.0

func (p *ConfigProvider) UpdatePasswordHash(ctx context.Context, name, newHash string) error

UpdatePasswordHash replaces the password hash in an existing Secret and removes any plaintext password key (used once a user sets their own password).

func (*ConfigProvider) UpdateUser

UpdateUser updates an existing User CR.

func (*ConfigProvider) UpdateUserStatus

UpdateUserStatus updates the status subresource of a User CR.

type IDTokenClaims

type IDTokenClaims struct {
	Sub           string   `json:"sub"`
	Email         string   `json:"email"`
	EmailVerified bool     `json:"email_verified"`
	Name          string   `json:"name"`
	Picture       string   `json:"picture"`
	Groups        []string `json:"groups"`
}

IDTokenClaims represents relevant claims from the ID token.

type LocalAuthHandler added in v0.3.0

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

LocalAuthHandler handles local (username/password) authentication.

func NewLocalAuthHandler added in v0.3.0

func NewLocalAuthHandler(provider *ConfigProvider) *LocalAuthHandler

NewLocalAuthHandler creates a new LocalAuthHandler.

func (*LocalAuthHandler) HandleChangePassword added in v0.3.0

func (h *LocalAuthHandler) HandleChangePassword(w http.ResponseWriter, r *http.Request)

HandleChangePassword lets an authenticated local user set a new password. Note: the auth middleware skips /auth/* paths, so this handler must validate the session token directly (mirrors OIDCHandler.HandleMe): session cookie first, then an Authorization: Bearer header for native/API clients.

func (*LocalAuthHandler) HandleLocalLogin added in v0.3.0

func (h *LocalAuthHandler) HandleLocalLogin(w http.ResponseWriter, r *http.Request)

HandleLocalLogin authenticates a user via email/password and, on success, issues the same kind of session token/cookie as the OIDC flow.

type OIDCDiscovery

type OIDCDiscovery struct {
	AuthorizationEndpoint string `json:"authorization_endpoint"`
	TokenEndpoint         string `json:"token_endpoint"`
	UserinfoEndpoint      string `json:"userinfo_endpoint"`
	JwksURI               string `json:"jwks_uri"`
}

OIDCDiscovery holds the endpoints from .well-known/openid-configuration.

type OIDCHandler

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

OIDCHandler handles the OIDC authentication flow.

func NewOIDCHandler

func NewOIDCHandler(provider *ConfigProvider) *OIDCHandler

NewOIDCHandler creates a new OIDC handler.

func (*OIDCHandler) Close added in v0.5.0

func (h *OIDCHandler) Close()

Close releases background resources held by the handler (the native authorization code sweeper).

func (*OIDCHandler) HandleAuthConfig

func (h *OIDCHandler) HandleAuthConfig(w http.ResponseWriter, r *http.Request)

HandleAuthConfig returns public auth configuration for the frontend.

func (*OIDCHandler) HandleBrowserSessionGrant added in v0.5.0

func (h *OIDCHandler) HandleBrowserSessionGrant(w http.ResponseWriter, r *http.Request)

HandleBrowserSessionGrant mints a single-use code that, redeemed in a browser, sets a session cookie and redirects to the given /proxy/... target.

The endpoint authenticates with the caller's existing session token (Bearer header for the desktop client, cookie for a browser) — it never accepts an unauthenticated request, because there is no session to grant then.

func (*OIDCHandler) HandleBrowserSessionRedeem added in v0.5.0

func (h *OIDCHandler) HandleBrowserSessionRedeem(w http.ResponseWriter, r *http.Request)

HandleBrowserSessionRedeem sets the session cookie for a code issued by OIDCHandler.HandleBrowserSessionGrant and redirects to the grant's target.

This is a browser navigation, so failures render a small HTML page rather than a JSON error: the person looking at it is the user, not an API client.

func (*OIDCHandler) HandleCallback

func (h *OIDCHandler) HandleCallback(w http.ResponseWriter, r *http.Request)

HandleCallback handles the OIDC callback after authentication.

func (*OIDCHandler) HandleLogin

func (h *OIDCHandler) HandleLogin(w http.ResponseWriter, r *http.Request)

HandleLogin initiates the OIDC login flow.

func (*OIDCHandler) HandleLogout

func (h *OIDCHandler) HandleLogout(w http.ResponseWriter, r *http.Request)

HandleLogout clears the session.

func (*OIDCHandler) HandleMe

func (h *OIDCHandler) HandleMe(w http.ResponseWriter, r *http.Request)

HandleMe returns the current user's information. Note: The auth middleware skips /auth/* paths, so this handler must validate the session token directly. It accepts the session cookie (browser) or an Authorization: Bearer header (native/API clients, which cannot read an HttpOnly cookie); the cookie takes precedence.

func (*OIDCHandler) HandleNativeToken added in v0.5.0

func (h *OIDCHandler) HandleNativeToken(w http.ResponseWriter, r *http.Request)

HandleNativeToken exchanges a single-use authorization code, issued by the native branch of /auth/callback, for the session token it stands for.

Unlike every other token delivery path in this service the token is returned in the response body: a native app cannot read an HttpOnly cookie, which is the whole reason this endpoint exists.

type PersonalNamespacesConfig

type PersonalNamespacesConfig struct {
	Enabled  bool
	Template string
}

PersonalNamespacesConfig holds personal namespace settings.

type RegistrationConfig

type RegistrationConfig struct {
	AutoProvision   bool
	DefaultRole     string
	AllowedDomains  []string
	AllowedEmails   []string
	RequireApproval bool
}

RegistrationConfig holds user registration settings.

type SessionToken

type SessionToken struct {
	Email       string   `json:"email"`
	DisplayName string   `json:"displayName,omitempty"`
	Role        string   `json:"role"`
	Groups      []string `json:"groups,omitempty"`
	IssuedAt    int64    `json:"iat"`
	ExpiresAt   int64    `json:"exp"`
}

SessionToken represents a JWT-like session token.

func ValidateSessionToken

func ValidateSessionToken(tokenStr string, signingKey []byte) (*SessionToken, error)

ValidateSessionToken validates and decodes a session token signed with the given signing key.

func ValidateSessionTokenWithKeys added in v0.4.0

func ValidateSessionTokenWithKeys(tokenStr string, signingKeys [][]byte) (*SessionToken, error)

ValidateSessionTokenWithKeys validates and decodes a session token against any of the given signing keys. The current key should be first; keys retired by rotation should follow so that sessions minted before the rotation remain valid while they expire naturally.

type TokenResponse

type TokenResponse struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    int    `json:"expires_in"`
	RefreshToken string `json:"refresh_token"`
	IDToken      string `json:"id_token"`
}

TokenResponse represents the OIDC token response.

type UserInfo

type UserInfo struct {
	Email       string   `json:"email"`
	DisplayName string   `json:"displayName,omitempty"`
	Role        string   `json:"role"`
	Groups      []string `json:"groups,omitempty"`
	// Namespaces the user has access to (populated at request time)
	Namespaces []string `json:"namespaces,omitempty"`
	// PersonalNamespace is the user's personal namespace
	PersonalNamespace string `json:"personalNamespace,omitempty"`
	// AvatarURL is the URL to the user's avatar image
	AvatarURL string `json:"avatarURL,omitempty"`
	// MustChangePassword indicates a local-auth user must set a new password
	// before continuing (set on creation/reset by an admin).
	MustChangePassword bool `json:"mustChangePassword,omitempty"`
}

UserInfo represents the authenticated user's identity extracted from the session token.

func UserFromContext

func UserFromContext(ctx context.Context) *UserInfo

UserFromContext extracts the authenticated user from the request context. Returns nil if no user is authenticated (auth disabled or unauthenticated request).

Jump to

Keyboard shortcuts

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