server

package
v0.7.2 Latest Latest
Warning

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

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

Documentation

Overview

Package server provides OAuth 2.1 protection for the Muster Server.

This package implements ADR 005 (OAuth Protection for Muster Server), allowing the Muster Server to act as an OAuth Resource Server. When enabled, all MCP endpoints require valid access tokens from authenticated clients.

Architecture

The server package integrates with the mcp-oauth library to provide:

  • OAuth 2.1 server with mandatory PKCE
  • Dynamic client registration (RFC 7591)
  • Client ID Metadata Documents (CIMD) per MCP 2025-11-25 spec
  • Token validation middleware for protecting MCP endpoints
  • Multiple provider support (Dex OIDC, Google OAuth)
  • Token storage backends (in-memory, Valkey/Redis)

Integration

The OAuth server wraps the existing aggregator HTTP handler, adding authentication and authorization before requests reach MCP endpoints.

┌─────────────────────────────────────────────────────────────┐
│                      Muster Server                          │
│                                                             │
│  [ OAuth Middleware (Resource Server) ]                     │
│       Validates Token from Agent                            │
│               │                                             │
│               ▼                                             │
│  [ Aggregator / Tool Handler ]                              │
│               │                                             │
│               ▼                                             │
│  [ OAuth Proxy (Client) ]                                   │
│       Injects Token for Remote MCPs                         │
└─────────────────────────────────────────────────────────────┘

Usage

To enable OAuth server protection, configure the aggregator with:

aggregator:
  oauthServer:
    enabled: true
    baseUrl: "https://muster.example.com"
    provider: "dex"
    dex:
      issuerUrl: "https://dex.example.com"
      clientId: "muster-server"
      clientSecret: "${DEX_CLIENT_SECRET}"

Endpoints

When OAuth server is enabled, the following endpoints are exposed:

  • /.well-known/oauth-authorization-server - Authorization Server Metadata (RFC 8414)
  • /.well-known/oauth-protected-resource - Protected Resource Metadata (RFC 9728)
  • /oauth/register - Dynamic Client Registration (RFC 7591)
  • /oauth/authorize - OAuth Authorization
  • /oauth/token - Token Endpoint
  • /oauth/callback - OAuth Callback (from IdP)
  • /oauth/revoke - Token Revocation (RFC 7009)
  • /mcp - Protected MCP endpoint (requires Bearer token)

Index

Constants

View Source
const (
	// OAuthProviderDex is the Dex OIDC provider type.
	OAuthProviderDex = "dex"
	// OAuthProviderGoogle is the Google OAuth provider type.
	OAuthProviderGoogle = "google"

	// DefaultAccessTokenTTL is the configured TTL for access tokens (30 minutes).
	// This is intentionally set to match the Dex idTokens expiry (30m) so that
	// capTokenExpiry in mcp-oauth doesn't need to cap it further. If Dex's
	// idTokens expiry is shorter than this value, capTokenExpiry will
	// automatically reduce the effective TTL to match the provider's token lifetime.
	DefaultAccessTokenTTL = 30 * time.Minute

	// DefaultRefreshTokenTTL is the server-side TTL for refresh tokens.
	// Derived from pkgoauth.DefaultSessionDuration to keep server and CLI in sync.
	// Aligned with Dex's absoluteLifetime (720h = 30 days). Note: muster uses a
	// rolling TTL (reset on each rotation), while Dex's absoluteLifetime is
	// measured from original issuance and does NOT reset.
	DefaultRefreshTokenTTL = pkgoauth.DefaultSessionDuration

	// DefaultIPRateLimit is the default rate limit for requests per IP (requests/second).
	// In Kubernetes deployments, traffic may arrive from multiple distinct IPs or be
	// NATed through an ingress, so per-IP limits should be generous enough to avoid
	// false positives while still protecting against abuse.
	DefaultIPRateLimit = 50
	// DefaultIPBurst is the default burst size for IP rate limiting.
	DefaultIPBurst = 100

	// DefaultUserRateLimit is the default rate limit for authenticated users (requests/second).
	DefaultUserRateLimit = 100
	// DefaultUserBurst is the default burst size for authenticated user rate limiting.
	DefaultUserBurst = 200

	// DefaultMaxClientsPerIP is the default maximum number of clients per IP address.
	DefaultMaxClientsPerIP = 10

	// DefaultSecurityEventRate bounds security-event log emission (events/second
	// per keyed event), keeping a malformed-token attack from flooding the audit
	// pipeline. Mirrors mcp-oauth's production-example default (1, 5).
	DefaultSecurityEventRate = 1
	// DefaultSecurityEventBurst is the burst size for security-event log emission.
	DefaultSecurityEventBurst = 5

	// DefaultMetadataFetchRate is the per-domain rate for CIMD outbound metadata
	// fetches (requests/second). Prevents a misbehaving or malicious client from
	// triggering unbounded outbound HTTP requests to arbitrary domains.
	DefaultMetadataFetchRate = 1
	// DefaultMetadataFetchBurst is the burst size for CIMD metadata fetch rate limiting.
	DefaultMetadataFetchBurst = 3

	// DefaultReadHeaderTimeout is the default timeout for reading request headers.
	DefaultReadHeaderTimeout = 10 * time.Second
	// DefaultWriteTimeout is the default timeout for writing responses.
	DefaultWriteTimeout = 120 * time.Second
	// DefaultIdleTimeout is the default idle timeout for keepalive connections.
	DefaultIdleTimeout = 120 * time.Second
)

Variables

This section is empty.

Functions

func ContextWithIDToken added in v0.1.26

func ContextWithIDToken(ctx context.Context, idToken string) context.Context

ContextWithIDToken creates a context with the given OIDC ID token. This is used to pass the user's ID token for downstream authentication (e.g., to remote MCP servers).

func GetIDToken

func GetIDToken(token *oauth2.Token) string

GetIDToken extracts the ID token from an OAuth2 token. OIDC providers include an id_token in the Extra data. Kubernetes OIDC authentication requires the ID token, not the access token.

func GetIDTokenFromContext added in v0.1.26

func GetIDTokenFromContext(ctx context.Context) (string, bool)

GetIDTokenFromContext retrieves the OIDC ID token from the context. Returns the ID token and true if present, or empty string and false if not available.

Types

type LazyOAuthHTTPServer added in v0.1.209

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

LazyOAuthHTTPServer wraps OAuthHTTPServer construction behind a background retry loop. The HTTP handler surface is available immediately but returns 503 until OIDC discovery against the upstream Dex/OIDC issuer succeeds. All non-OAuth paths (MCP aggregation, reconcilers) are unaffected and start immediately.

func NewLazyOAuthHTTPServer added in v0.1.209

func NewLazyOAuthHTTPServer(ctx context.Context, cfg config.OAuthServerConfig, mcpHandler http.Handler, debug bool, opts ...oauth.ServerOption) *LazyOAuthHTTPServer

NewLazyOAuthHTTPServer creates a lazy OAuth HTTP server that starts a background goroutine to perform OIDC discovery with exponential backoff. It always returns successfully; the caller gets a handler that serves 503 until discovery succeeds.

func (*LazyOAuthHTTPServer) CreateMux added in v0.1.209

func (l *LazyOAuthHTTPServer) CreateMux() http.Handler

CreateMux returns an http.Handler that proxies to the inner mux once ready. Before OIDC discovery succeeds, /health returns a degraded-status JSON body and all other paths return 503.

func (*LazyOAuthHTTPServer) RefreshSession added in v0.5.4

func (l *LazyOAuthHTTPServer) RefreshSession(ctx context.Context, familyID string) error

RefreshSession forces an in-process upstream provider token refresh for the given token family. Returns an error if OIDC discovery has not yet completed.

func (*LazyOAuthHTTPServer) SetOnAuthenticated added in v0.1.209

func (l *LazyOAuthHTTPServer) SetOnAuthenticated(fn func(context.Context, string))

SetOnAuthenticated stores the callback and forwards it to the inner server once ready. Safe to call before or after discovery completes.

func (*LazyOAuthHTTPServer) Shutdown added in v0.1.209

func (l *LazyOAuthHTTPServer) Shutdown(ctx context.Context) error

Shutdown stops the discovery loop and shuts down the inner server if it was created. It waits for the background goroutine to exit so the caller can be sure no new inner server connections will be opened after Shutdown returns.

func (*LazyOAuthHTTPServer) ValidateTokenWithSubject added in v0.1.209

func (l *LazyOAuthHTTPServer) ValidateTokenWithSubject(next http.Handler) http.Handler

ValidateTokenWithSubject returns a middleware that delegates to the inner server once OIDC discovery has succeeded. Before that it returns 503.

func (*LazyOAuthHTTPServer) WaitReady added in v0.1.209

func (l *LazyOAuthHTTPServer) WaitReady(ctx context.Context) error

WaitReady blocks until OIDC discovery succeeds or the context is cancelled. Intended for tests and health-check endpoints that need to synchronise on readiness.

type OAuthHTTPServer

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

OAuthHTTPServer wraps an MCP HTTP handler with OAuth 2.1 authentication. It provides both OAuth server functionality (authorization, token issuance) and resource server protection (token validation middleware).

func NewOAuthHTTPServer

func NewOAuthHTTPServer(cfg config.OAuthServerConfig, mcpHandler http.Handler, debug bool, opts ...oauth.ServerOption) (*OAuthHTTPServer, error)

NewOAuthHTTPServer creates a new OAuth-enabled HTTP server that wraps the provided MCP handler with authentication protection. Caller-provided mcp-oauth options (e.g. token-family lifecycle handlers) are forwarded to the underlying OAuth server.

func (*OAuthHTTPServer) CreateMux

func (s *OAuthHTTPServer) CreateMux() http.Handler

CreateMux creates an HTTP mux that routes to both OAuth and MCP handlers. The MCP endpoints are protected by the OAuth ValidateToken middleware.

func (*OAuthHTTPServer) GetOAuthHandler

func (s *OAuthHTTPServer) GetOAuthHandler() *oauthhandler.Handler

GetOAuthHandler returns the OAuth handler for testing or direct access.

func (*OAuthHTTPServer) GetOAuthServer

func (s *OAuthHTTPServer) GetOAuthServer() *oauth.Server

GetOAuthServer returns the underlying OAuth server for testing or direct access.

func (*OAuthHTTPServer) GetTokenStore

func (s *OAuthHTTPServer) GetTokenStore() storage.TokenStore

GetTokenStore returns the token store for downstream OAuth passthrough.

func (*OAuthHTTPServer) RefreshSession added in v0.5.4

func (s *OAuthHTTPServer) RefreshSession(ctx context.Context, familyID string) error

RefreshSession forces an in-process upstream provider token refresh for the given token family. Delegates to the underlying mcp-oauth Server.RefreshSession so that TokenRefreshHandler fires and the SSO proxy store is updated before the caller re-reads the ID token.

func (*OAuthHTTPServer) SetOnAuthenticated added in v0.1.59

func (s *OAuthHTTPServer) SetOnAuthenticated(fn func(ctx context.Context, sessionID string))

SetOnAuthenticated registers a callback that fires on every authenticated MCP request after the session ID has been extracted. The aggregator uses this to trigger on-demand SSO connections from the HTTP middleware rather than from individual MCP operations.

func (*OAuthHTTPServer) Shutdown

func (s *OAuthHTTPServer) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the server.

func (*OAuthHTTPServer) ValidateTokenWithSubject added in v0.1.44

func (s *OAuthHTTPServer) ValidateTokenWithSubject(next http.Handler) http.Handler

ValidateTokenWithSubject wraps the given handler with OAuth token validation and extracts the authenticated user's subject (sub claim) into the context. This is used for API endpoints that need to identify the user but don't need the full SSO/token-injection logic of the MCP middleware chain.

type UserInfo

type UserInfo = providers.UserInfo

UserInfo represents user information from an OAuth provider. This is a type alias for the library's providers.UserInfo type.

Jump to

Keyboard shortcuts

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