Documentation
¶
Overview ¶
Package auth provides authentication for Virtual MCP Server.
This package defines:
- Identity: Domain type representing an authenticated user/service
- Claims → Identity conversion (incoming authentication)
- OutgoingAuthenticator: Authenticates vMCP to backend servers
- Strategy: Pluggable authentication strategies for backends
Incoming authentication uses pkg/auth.TokenValidator + IdentityMiddleware to validate OIDC tokens and convert Claims to Identity.
Index ¶
- func IdentityMiddleware(next http.Handler) http.Handler
- func NewIncomingAuthMiddleware(ctx context.Context, cfg *config.IncomingAuthConfig) (func(http.Handler) http.Handler, http.Handler, error)
- func WithIdentity(ctx context.Context, identity *Identity) context.Context
- type Authorizer
- type DefaultOutgoingAuthenticator
- func (a *DefaultOutgoingAuthenticator) AuthenticateRequest(ctx context.Context, req *http.Request, strategyName string, ...) error
- func (a *DefaultOutgoingAuthenticator) GetStrategy(name string) (Strategy, error)
- func (a *DefaultOutgoingAuthenticator) RegisterStrategy(name string, strategy Strategy) error
- type Identity
- type IdentityContextKey
- type OutgoingAuthenticator
- type Strategy
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IdentityMiddleware ¶ added in v0.5.2
IdentityMiddleware creates middleware that converts Claims → Identity. This middleware must run AFTER auth.TokenValidator.Middleware() which stores Claims in context.
Flow:
- Extracts Claims from context (stored by TokenValidator)
- Extracts original Bearer token from Authorization header
- Converts Claims → Identity using claimsToIdentity
- Stores Identity in context for downstream handlers
If no claims are present in context, the request passes through unchanged. This allows unauthenticated endpoints (like /health) to work without auth.
func NewIncomingAuthMiddleware ¶ added in v0.5.2
func NewIncomingAuthMiddleware( ctx context.Context, cfg *config.IncomingAuthConfig, ) (func(http.Handler) http.Handler, http.Handler, error)
NewIncomingAuthMiddleware creates HTTP middleware for incoming authentication based on the vMCP configuration.
This factory handles all incoming auth types:
- "oidc": OIDC token validation
- "local": Local OS user authentication
- "anonymous": Anonymous user (no authentication required)
All auth types are composed with IdentityMiddleware to provide consistent Identity context injection.
Flow (all types):
- AuthMiddleware validates/creates Claims and stores in context
- IdentityMiddleware converts Claims → Identity and stores in context
Returns:
- Composed middleware function (AuthMiddleware → IdentityMiddleware)
- AuthInfo handler (for /.well-known/oauth-protected-resource endpoint, may be nil)
- Error if middleware creation fails
func WithIdentity ¶ added in v0.5.2
WithIdentity stores an Identity in the context. If identity is nil, the original context is returned unchanged.
This function is typically called by authentication middleware after successful authentication to make the identity available to downstream handlers.
Example:
identity := &Identity{Subject: "user123", Name: "Alice"}
ctx = WithIdentity(ctx, identity)
Types ¶
type Authorizer ¶
type Authorizer interface {
// Authorize checks if an identity is authorized to perform an action on a resource.
Authorize(ctx context.Context, identity *Identity, action string, resource string) error
// AuthorizeToolCall checks if an identity can call a specific tool.
AuthorizeToolCall(ctx context.Context, identity *Identity, toolName string) error
// AuthorizeResourceAccess checks if an identity can access a specific resource.
AuthorizeResourceAccess(ctx context.Context, identity *Identity, resourceURI string) error
}
Authorizer handles authorization decisions. This integrates with ToolHive's existing Cedar-based authorization.
type DefaultOutgoingAuthenticator ¶ added in v0.5.2
type DefaultOutgoingAuthenticator struct {
// contains filtered or unexported fields
}
DefaultOutgoingAuthenticator is a thread-safe implementation of OutgoingAuthenticator that maintains a registry of authentication strategies.
Thread-safety: Safe for concurrent calls to RegisterStrategy and AuthenticateRequest. Strategy implementations must be thread-safe as they are called concurrently. It uses sync.RWMutex for thread-safety as HTTP servers are inherently concurrent.
This authenticator supports dynamic registration of strategies and dispatches authentication requests to the appropriate strategy based on the strategy name.
Example usage:
auth := NewDefaultOutgoingAuthenticator()
auth.RegisterStrategy("bearer", NewBearerStrategy())
err := auth.AuthenticateRequest(ctx, req, "bearer", metadata)
func NewDefaultOutgoingAuthenticator ¶ added in v0.5.2
func NewDefaultOutgoingAuthenticator() *DefaultOutgoingAuthenticator
NewDefaultOutgoingAuthenticator creates a new DefaultOutgoingAuthenticator with an empty strategy registry.
Strategies must be registered using RegisterStrategy before they can be used for authentication.
func (*DefaultOutgoingAuthenticator) AuthenticateRequest ¶ added in v0.5.2
func (a *DefaultOutgoingAuthenticator) AuthenticateRequest( ctx context.Context, req *http.Request, strategyName string, metadata map[string]any, ) error
AuthenticateRequest adds authentication to an outgoing backend request.
This method retrieves the specified strategy and delegates authentication to it. The strategy modifies the request by adding appropriate headers, tokens, or other authentication artifacts.
Parameters:
- ctx: Request context (may contain identity for pass-through auth)
- req: The HTTP request to authenticate
- strategyName: The name of the strategy to use
- metadata: Strategy-specific configuration
Returns an error if:
- The strategy is not found
- The metadata validation fails
- The strategy's Authenticate method fails
func (*DefaultOutgoingAuthenticator) GetStrategy ¶ added in v0.5.2
func (a *DefaultOutgoingAuthenticator) GetStrategy(name string) (Strategy, error)
GetStrategy retrieves an authentication strategy by name.
This method is thread-safe for concurrent reads. It returns the strategy if found, or an error if no strategy is registered with the given name.
Parameters:
- name: The identifier of the strategy to retrieve
Returns:
- Strategy: The registered strategy
- error: An error if the strategy is not found
func (*DefaultOutgoingAuthenticator) RegisterStrategy ¶ added in v0.5.2
func (a *DefaultOutgoingAuthenticator) RegisterStrategy(name string, strategy Strategy) error
RegisterStrategy registers a new authentication strategy.
This method is thread-safe and validates that:
- name is not empty
- strategy is not nil
- no strategy is already registered with the same name
Parameters:
- name: The unique identifier for this strategy
- strategy: The Strategy implementation to register
Returns an error if validation fails or a strategy with the same name already exists.
type Identity ¶
type Identity struct {
// Subject is the unique identifier for the principal.
Subject string
// Name is the human-readable name.
Name string
// Email is the email address (if available).
Email string
// Groups are the groups this identity belongs to.
//
// NOTE: This field is intentionally NOT populated by OIDCIncomingAuthenticator.
// Authorization logic MUST extract groups from the Claims map, as group claim
// names vary by provider (e.g., "groups", "roles", "cognito:groups").
Groups []string
// Claims contains additional claims from the auth token.
Claims map[string]any
// Token is the original authentication token (for pass-through).
Token string
// TokenType is the type of token (e.g., "Bearer", "JWT").
TokenType string
// Metadata stores additional identity information.
Metadata map[string]string
}
Identity represents an authenticated user or service account.
func IdentityFromContext ¶ added in v0.5.2
IdentityFromContext retrieves an Identity from the context. Returns the identity and true if present, nil and false otherwise.
This function is typically called by authorization middleware or handlers that need to check who the authenticated user is.
Example:
identity, ok := IdentityFromContext(ctx)
if !ok {
return errors.New("no authenticated identity")
}
log.Printf("Request from user: %s", identity.Subject)
func (*Identity) MarshalJSON ¶ added in v0.5.2
MarshalJSON implements json.Marshaler to redact sensitive fields during JSON serialization. This prevents accidental token leakage in structured logs, API responses, or audit logs.
type IdentityContextKey ¶ added in v0.5.2
type IdentityContextKey struct{}
IdentityContextKey is the key used to store Identity in the request context. This provides type-safe context storage and retrieval for authenticated identities.
Using an empty struct as the key prevents collisions with other context keys, as each empty struct type is distinct even if they have the same name in different packages.
type OutgoingAuthenticator ¶
type OutgoingAuthenticator interface {
// AuthenticateRequest adds authentication to an outgoing backend request.
// The strategy and metadata are provided in the BackendTarget.
AuthenticateRequest(ctx context.Context, req *http.Request, strategy string, metadata map[string]any) error
// GetStrategy returns the authentication strategy handler for a given strategy name.
// This enables extensibility - new strategies can be registered.
GetStrategy(name string) (Strategy, error)
// RegisterStrategy registers a new authentication strategy.
// This allows custom auth strategies to be added at runtime.
RegisterStrategy(name string, strategy Strategy) error
}
OutgoingAuthenticator handles authentication to backend MCP servers. This is responsible for obtaining and injecting appropriate credentials for each backend based on its authentication strategy.
The specific authentication strategies and their behavior will be defined during implementation based on the design decisions documented in the Virtual MCP Server proposal.
type Strategy ¶
type Strategy interface {
// Name returns the strategy identifier.
Name() string
// Authenticate performs authentication and modifies the request.
// The metadata contains strategy-specific configuration.
Authenticate(ctx context.Context, req *http.Request, metadata map[string]any) error
// Validate checks if the strategy configuration is valid.
Validate(metadata map[string]any) error
}
Strategy defines how to authenticate to a backend. This interface enables pluggable authentication strategies.