auth

package
v0.52.0-rc.2 Latest Latest
Warning

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

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package auth provides agent token authentication for MCPProxy.

It implements token generation, validation, HMAC-based hashing, and context propagation for distinguishing admin vs agent access. Agent tokens use the "mcp_agt_" prefix and are secured with HMAC-SHA256 hashing before storage.

Index

Constants

View Source
const (
	PermRead        = "read"
	PermWrite       = "write"
	PermDestructive = "destructive"
)

Permission constants define the allowed permission tiers.

View Source
const (
	AuthTypeAdmin     = "admin"      // API key admin (personal edition)
	AuthTypeAgent     = "agent"      // Agent token authentication
	AuthTypeUser      = "user"       // Regular OAuth-authenticated user (server edition)
	AuthTypeAdminUser = "admin_user" // OAuth-authenticated admin (server edition)
)

Auth type constants.

View Source
const (
	ServerOpAdd             = "add"
	ServerOpRemove          = "remove"
	ServerOpUpdate          = "update"
	ServerOpPatch           = "patch"
	ServerOpEnable          = "enable"
	ServerOpDisable         = "disable"
	ServerOpRestart         = "restart"
	ServerOpRefresh         = "refresh"
	ServerOpDiscoverTools   = "discover_tools"
	ServerOpQuarantine      = "quarantine"
	ServerOpUnquarantine    = "unquarantine"
	ServerOpAddFromRegistry = "add_from_registry"
	ServerOpLogin           = "login"
	ServerOpLogout          = "logout"
	ServerOpConfigToSecret  = "config_to_secret"
	ServerOpApproveTools    = "approve_tools"
	ServerOpBlockTools      = "block_tools"

	// REST-only mutating operations that reach server/security/config state
	// through routes OTHER than /api/v1/servers/{id}. They are denied to agents
	// so the /servers gate cannot be bypassed via a sibling endpoint
	// (config apply rewrites mcpServers; registry add creates a server; the
	// security scanner mutates a server's approval state).
	ServerOpConfigWrite     = "config_write"
	ServerOpScan            = "scan"
	ServerOpSecurityApprove = "security_approve"
	ServerOpSecurityReject  = "security_reject"
	ServerOpSecretWrite     = "secret_write"
	ServerOpDiagnosticsFix  = "diagnostics_fix"
)

Server-mutating operation identifiers.

These name the write operations on upstream MCP servers that are exposed on BOTH the MCP `upstream_servers` / `quarantine_security` tools and the REST `/api/v1/servers/...` surface. They are the single source of truth for which operations agent tokens (non-admin) may NOT perform, so the two surfaces can never drift apart again (issues #877/#878).

The string values for the operations that also exist on the MCP `upstream_servers` tool intentionally match that tool's operation names (see internal/server/mcp.go: operationAdd/operationRemove and the literal "update"/"patch"/"enable"/"disable"/"restart"/"refresh"/"add_from_registry" dispatch), so the MCP denylist can consume this policy without changing its observable behavior. REST-only operations (quarantine, login, …) use their own identifiers; the MCP surface never passes those strings here, so listing them is a no-op for MCP and closes the REST gap.

View Source
const MaxTokens = 100

MaxTokens is the maximum number of agent tokens allowed.

View Source
const TokenPrefixStr = "mcp_agt_"

Token prefix used for all agent tokens.

Variables

This section is empty.

Functions

func AgentDeniedServerOp

func AgentDeniedServerOp(op string) bool

AgentDeniedServerOp reports whether the named operation is forbidden to agent tokens (non-admin auth contexts). It is case-sensitive: callers pass the canonical ServerOp* identifiers, never user-controlled free text.

func AuthorizeServerOp

func AuthorizeServerOp(ac *AuthContext, op string) bool

AuthorizeServerOp is the shared gate both surfaces use. It returns true when the caller is permitted to perform op. An admin context (API key or OS-authenticated socket) is always allowed. A nil context means the request arrived without an AuthContext — the auth middleware only leaves it nil in test/no-config passthrough scenarios that never occur once a real *config.Config is loaded, so it is treated as allowed here (the middleware, not this policy, is responsible for rejecting unauthenticated production requests). Any present non-admin context (agent token) is denied when op is on the denylist.

func GenerateToken

func GenerateToken() (string, error)

GenerateToken creates a new agent token with the mcp_agt_ prefix followed by 64 hex characters (32 random bytes). Total length: 72 chars.

func GetOrCreateHMACKey

func GetOrCreateHMACKey(dataDir string) ([]byte, error)

GetOrCreateHMACKey reads the HMAC key from <dataDir>/.token_key. If the file does not exist, it generates a 32-byte random key, writes it with 0600 permissions, and returns it.

func HashToken

func HashToken(token string, key []byte) string

HashToken computes HMAC-SHA256 of the token using the given key and returns the hex-encoded digest.

func TokenPrefix

func TokenPrefix(token string) string

TokenPrefix returns the first 12 characters of the token for display purposes.

func ValidatePermissions

func ValidatePermissions(perms []string) error

ValidatePermissions checks that the given permissions list is valid. It must contain "read" and only contain valid permission values.

func ValidateTokenFormat

func ValidateTokenFormat(token string) bool

ValidateTokenFormat checks that a token has the correct format: mcp_agt_ prefix followed by exactly 64 hex characters (72 chars total).

func WithAuthContext

func WithAuthContext(ctx context.Context, ac *AuthContext) context.Context

WithAuthContext returns a new context with the given AuthContext attached.

Types

type AgentToken

type AgentToken struct {
	Name           string     `json:"name"`
	TokenHash      string     `json:"token_hash"`
	TokenPrefix    string     `json:"token_prefix"` // first 12 chars of the raw token
	AllowedServers []string   `json:"allowed_servers"`
	Permissions    []string   `json:"permissions"`
	ExpiresAt      time.Time  `json:"expires_at"`
	CreatedAt      time.Time  `json:"created_at"`
	LastUsedAt     *time.Time `json:"last_used_at,omitempty"`
	Revoked        bool       `json:"revoked"`
	UserID         string     `json:"user_id,omitempty"`     // Owner user ID (server edition)
	ProfilePin     string     `json:"profile_pin,omitempty"` // Profile this token is pinned to (Profiles v2 T3)
}

AgentToken represents a stored agent token record.

func (*AgentToken) IsExpired

func (t *AgentToken) IsExpired() bool

IsExpired returns true if the token has passed its expiry time.

func (*AgentToken) IsRevoked

func (t *AgentToken) IsRevoked() bool

IsRevoked returns true if the token has been revoked.

type AuthContext

type AuthContext struct {
	Type           string   // "admin", "agent", "user", or "admin_user"
	AgentName      string   // Name of the agent token (empty for admin)
	TokenPrefix    string   // First 12 chars of raw token (empty for admin)
	AllowedServers []string // Servers this token can access (nil = all for admin)
	Permissions    []string // Permission tiers (nil = all for admin)
	ProfilePin     string   // Profile this agent token is pinned to (Profiles v2 T3; empty if unpinned)

	// Multi-user OAuth fields (server edition). Empty for non-user auth types.
	UserID      string // User's unique ULID identifier
	Email       string // User's email from OAuth provider
	DisplayName string // User's display name
	Role        string // "admin" or "user" (empty for API key / agent token auth)
	Provider    string // OAuth provider used (e.g., "google", "github")
}

AuthContext carries authentication identity through request context.

func AdminContext

func AdminContext() *AuthContext

AdminContext returns an AuthContext representing full admin access (API key auth).

func AdminUserContext added in v0.21.0

func AdminUserContext(userID, email, displayName, provider string) *AuthContext

AdminUserContext returns an AuthContext for an OAuth-authenticated admin user.

func AuthContextFromContext

func AuthContextFromContext(ctx context.Context) *AuthContext

AuthContextFromContext extracts the AuthContext from the context. Returns nil if no AuthContext is present.

func UserContext added in v0.21.0

func UserContext(userID, email, displayName, provider string) *AuthContext

UserContext returns an AuthContext for a regular OAuth-authenticated user.

func (*AuthContext) CanAccessServer

func (ac *AuthContext) CanAccessServer(name string) bool

CanAccessServer checks whether this context is allowed to access the named server. Admin contexts have unrestricted access. Agent contexts check their AllowedServers list, where "*" is treated as a wildcard granting access to all servers.

func (*AuthContext) GetUserID added in v0.21.0

func (ac *AuthContext) GetUserID() string

GetUserID returns the user's unique identifier, or empty string for non-user auth.

func (*AuthContext) HasPermission

func (ac *AuthContext) HasPermission(perm string) bool

HasPermission checks whether this context includes the given permission. Admin contexts have all permissions. Agent contexts check their Permissions list.

func (*AuthContext) IsAdmin

func (ac *AuthContext) IsAdmin() bool

IsAdmin returns true if this is an admin authentication context. Both API key admins ("admin") and OAuth-authenticated admins ("admin_user") are considered admin.

func (*AuthContext) IsAuthenticated added in v0.21.0

func (ac *AuthContext) IsAuthenticated() bool

IsAuthenticated returns true if this context has any authentication type set.

func (*AuthContext) IsUser added in v0.21.0

func (ac *AuthContext) IsUser() bool

IsUser returns true if this is an OAuth-authenticated user context. Both regular users ("user") and admin users ("admin_user") are considered users.

Jump to

Keyboard shortcuts

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