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

auth

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2026 License: Apache-2.0 Imports: 32 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 (
	// DeviceTokenType marks a session token as a revocable device credential.
	DeviceTokenType = "device"
)
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 BrowserOriginAllowed added in v0.10.0

func BrowserOriginAllowed(r *http.Request, allowed []string) bool

BrowserOriginAllowed validates an exact browser origin, independently of CORS. Headerless native clients may use bearer authentication, but a headerless cookie-authenticated WebSocket/mutation is rejected. Host/forwarded headers are not accepted as authority for the trusted browser-origin list.

func BrowserRequestGuard added in v0.10.0

func BrowserRequestGuard(allowed []string) func(http.Handler) http.Handler

BrowserRequestGuard protects WebSocket handshakes and state-changing requests before they reach logging, owner forwarding or authentication handlers. Native bearer clients do not need browser CSRF tokens; browser clients must supply an exact trusted Origin. Safe HTTP reads keep normal CORS response behavior.

func ContextWithUser

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

ContextWithUser adds user info to the context.

func CreateDeviceToken added in v0.6.0

func CreateDeviceToken(email, displayName, role string, groups []string, deviceName, jti string, signingKey []byte, expiry time.Duration, userUID ...string) (string, error)

CreateDeviceToken mints a long-lived device token. jti must be fresh random hex; name is human metadata (e.g. "ada-laptop") and is not unique.

func CreateSessionToken

func CreateSessionToken(email, displayName, role string, groups []string, signingKey []byte, expiry time.Duration, userUID ...string) (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 HasExecutionPermission added in v0.10.0

func HasExecutionPermission(user *UserInfo, namespace, workspace string, permission ExecutionPermission, now time.Time) bool

HasExecutionPermission is deliberately stricter than legacy auth-disabled helpers: no nil/anonymous or unbound principal, no implicit editor permission, and no grant can manufacture namespace membership. Policy/capability/recording admission must additionally be checked by the execution service.

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.

func WebSocketOriginAllowed added in v0.10.0

func WebSocketOriginAllowed(r *http.Request) bool

WebSocketOriginAllowed is also used at the upgrader boundary, so a bridge mounted outside the main HTTP stack cannot accidentally skip origin checks.

Types

type CodeStore added in v0.6.0

type CodeStore interface {
	Issue(code string, entry nativeAuthCode) error
	Redeem(code string) (nativeAuthCode, bool)
	Close()
}

CodeStore is the seam behind OIDCHandler.codes: single-use, TTL-bounded authorization codes shared by the RFC 8252 native login (native.go) and the browser-session grant (browsersession.go).

The in-memory nativeCodeStore implements this for single-replica use and for tests. The K8s-backed store below implements the same contract across replicas so a code issued on one pod redeems on any other.

func NewK8sCodeStore added in v0.6.0

func NewK8sCodeStore(dyn dynamic.Interface) CodeStore

NewK8sCodeStore returns a CodeStore backed by K8s Secrets when dyn is non-nil, or a pure in-memory store otherwise. TTL/max match the native flow defaults so callers do not repeat them.

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
	// DeviceTokenExpiry is the lifetime of long-lived revocable device tokens
	// (spec.session.deviceTokenExpiry, default 90d). Session tokens keep using
	// TokenExpiry.
	DeviceTokenExpiry       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) AuthorizeExecution added in v0.10.0

func (p *ConfigProvider) AuthorizeExecution(ctx context.Context, token, namespace, workspace string, operation ExecutionPermission, elevated bool, now time.Time) (*UserInfo, error)

AuthorizeExecution requires a fresh signed credential and a fresh User lookup on every invocation (admission AND renewal). It must not accept a caller-built UserInfo or a desktop-controller grant as machine execution authority.

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) DynamicClient added in v0.6.0

func (p *ConfigProvider) DynamicClient() dynamic.Interface

DynamicClient exposes the underlying dynamic client for stores that persist alongside the config (auth codes, device tokens). May be nil in tests.

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. Failed refreshes are cached too, but never expose a stale or disabled configuration.

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 DeviceHandler added in v0.6.0

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

DeviceHandler serves the device-token endpoints.

func NewDeviceHandler added in v0.6.0

func NewDeviceHandler(provider *ConfigProvider, devices *DeviceStore) *DeviceHandler

NewDeviceHandler creates the handler. devices may be a nil-client store.

func (*DeviceHandler) HandleDeviceCreate added in v0.6.0

func (h *DeviceHandler) HandleDeviceCreate(w http.ResponseWriter, r *http.Request)

HandleDeviceCreate mints a long-lived device token for the caller's own session. Body: {"name": "ada-laptop"} (human label, optional).

func (*DeviceHandler) HandleDeviceList added in v0.6.0

func (h *DeviceHandler) HandleDeviceList(w http.ResponseWriter, r *http.Request)

HandleDeviceList returns the caller's device registrations (admins see all, unless ?scope=own is supplied by the profile UI).

func (*DeviceHandler) HandleDeviceRevoke added in v0.6.0

func (h *DeviceHandler) HandleDeviceRevoke(w http.ResponseWriter, r *http.Request)

HandleDeviceRevoke deletes a device registration. Body: {"device_id": "..."}. Owners revoke their own devices; admins may revoke any.

type DeviceInfo added in v0.6.0

type DeviceInfo struct {
	DeviceID  string `json:"deviceId"`
	Name      string `json:"name"`
	CreatedAt int64  `json:"createdAt"`
	ExpiresAt int64  `json:"expiresAt"`
}

DeviceInfo is the metadata returned by list/create (never the token itself, except on create).

type DeviceStore added in v0.6.0

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

DeviceStore persists device registrations as Secrets. A nil dynamic client (unit tests, local runs) degrades to a closed store: create fails with a clear error, revocation checks pass through so session tokens keep working.

func NewDeviceStore added in v0.6.0

func NewDeviceStore(dyn dynamic.Interface) *DeviceStore

NewDeviceStore creates the store. dyn may be nil.

func (*DeviceStore) List added in v0.6.0

func (s *DeviceStore) List(ctx context.Context, email string, isAdmin bool) ([]DeviceInfo, error)

List returns the caller's device registrations (metadata only).

func (*DeviceStore) Register added in v0.6.0

func (s *DeviceStore) Register(ctx context.Context, email, name, jti string, createdAt, expiresAt time.Time) error

Register creates the backing Secret for a freshly minted device token.

func (*DeviceStore) Revoke added in v0.6.0

func (s *DeviceStore) Revoke(ctx context.Context, jti string) error

Revoke marks a device revoked (and deletes the Secret so list stops showing it). Callers must already have authorized ownership.

func (*DeviceStore) Revoked added in v0.6.0

func (s *DeviceStore) Revoked(ctx context.Context, jti, email string) bool

Revoked reports whether the device Secret is missing, revoked, expired, or bound to a different email. Missing means revoked: deleting the Secret is the revoke path.

type ExecutionGrant added in v0.10.0

type ExecutionGrant struct {
	Namespace   string                `json:"namespace"`
	Workspaces  []string              `json:"workspaces,omitempty"`
	Permissions []ExecutionPermission `json:"permissions"`
	ExpiresAt   *time.Time            `json:"expiresAt,omitempty"`
}

ExecutionGrant grants no namespace access by itself. Permissions from matching unexpired grants are additive, including separately granted elevation.

func ParseExecutionGrants added in v0.10.0

func ParseExecutionGrants(raw interface{}) ([]ExecutionGrant, error)

ParseExecutionGrants validates admin input as well as CR data. Strict decoding prevents misspelled scope fields from silently widening a grant.

type ExecutionPermission added in v0.10.0

type ExecutionPermission string

ExecutionPermission mirrors the controller-owned User.executionGrants schema.

const (
	PermissionExec           ExecutionPermission = "workspace.exec"
	PermissionShell          ExecutionPermission = "workspace.shell"
	PermissionElevated       ExecutionPermission = "workspace.exec.elevated"
	PermissionManage         ExecutionPermission = "workspace.execution.manage"
	PermissionReadRecordings ExecutionPermission = "workspace.execution.recordings.read"
)

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 NewOIDCHandlerWithCodes added in v0.6.0

func NewOIDCHandlerWithCodes(provider *ConfigProvider, codes CodeStore) *OIDCHandler

NewOIDCHandlerWithCodes creates a handler with an explicit code store. The HTTP wiring passes a K8s-backed store when cluster access exists so native and browser-session codes redeem on any replica; tests pass the in-memory store (or a fake-backed K8s store) directly.

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 {
	// UserUID binds new credentials to a User incarnation. Legacy credentials
	// remain usable for existing routes, but cannot authorize machine execution.
	UserUID     string   `json:"user_uid,omitempty"`
	Email       string   `json:"email"`
	DisplayName string   `json:"displayName,omitempty"`
	Role        string   `json:"role"`
	Groups      []string `json:"groups,omitempty"`
	// Type is empty for short-lived session tokens and "device" for
	// long-lived revocable device tokens (see device.go).
	Type string `json:"typ,omitempty"`
	// JTI is the device id for device tokens; empty otherwise.
	JTI       string `json:"jti,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 {
	// UID is the current User CR identity, not a caller-selected label.
	UID         string   `json:"uid,omitempty"`
	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"`
	// ExecutionGrants are loaded from the current User CR, never from a token.
	ExecutionGrants []ExecutionGrant `json:"-"`
	// contains filtered or unexported fields
}

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

func ExecutionPrincipal added in v0.10.0

func ExecutionPrincipal(ctx context.Context) *UserInfo

ExecutionPrincipal is the middleware-authenticated, current User identity. Legacy credentials remain valid for older routes but cannot access management.

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