Documentation
¶
Overview ¶
Package auth provides credential mechanisms for mcpmux's backend connections. The exec credential helper obtains a bearer token by running an external command (e.g. "chainctl auth token --audience <resource>"), re-running it only when the cached token is near expiry or has been rejected.
The types here implement golang.org/x/oauth2.TokenSource and the MCP SDK's auth.OAuthHandler interface (structurally), so they plug directly into a streamable-HTTP transport without this package depending on the SDK.
Index ¶
- func EagerAuthorize(ctx context.Context, h sdkauth.OAuthHandler, endpoint, label string, ...) error
- func NewOAuthHandler(ctx context.Context, log *slog.Logger, o OAuthOptions) (sdkauth.OAuthHandler, error)
- func RunString(ctx context.Context, argv []string) (string, error)
- type ExecHandler
- type ExecTokenSource
- type OAuthOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EagerAuthorize ¶ added in v0.4.0
func EagerAuthorize(ctx context.Context, h sdkauth.OAuthHandler, endpoint, label string, log *slog.Logger) error
EagerAuthorize forces an interactive OAuth handler to run its authorization-code flow now, instead of lazily on the first 401 from a tool call. This lets a daemon batch all browser consents at startup rather than surfacing them at random times mid session.
It is a no-op when the handler already holds a token — e.g. servers that challenge the initialize request authorize during connect, so only the lazy ones (whose initialize returns 200) are driven here. The 401 the handler expects is synthesized with an empty challenge; the SDK then discovers the protected-resource metadata from the endpoint's well-known path. Serialized with live flows via the shared authMu, so consents still open one at a time.
func NewOAuthHandler ¶
func NewOAuthHandler(ctx context.Context, log *slog.Logger, o OAuthOptions) (sdkauth.OAuthHandler, error)
NewOAuthHandler builds an OAuthHandler that performs the authorization-code flow in a browser, reserving a loopback callback endpoint for the daemon's lifetime (bounded by ctx). The SDK handles discovery, dynamic client registration, PKCE, token exchange and in-memory refresh.
Types ¶
type ExecHandler ¶
type ExecHandler struct {
// contains filtered or unexported fields
}
ExecHandler adapts an ExecTokenSource to the MCP SDK's auth.OAuthHandler interface: the transport sets the bearer header from TokenSource on every request, and calls Authorize on a 401/403 to force a fresh token.
func NewExecHandler ¶
func NewExecHandler(ts *ExecTokenSource) *ExecHandler
NewExecHandler wraps an ExecTokenSource as an OAuthHandler.
func (*ExecHandler) Authorize ¶
Authorize is invoked by the transport when a request fails with 401/403. It discards the cached token and mints a fresh one; on success the transport retries the request. It is responsible for closing the response body.
func (*ExecHandler) TokenSource ¶
func (h *ExecHandler) TokenSource(context.Context) (oauth2.TokenSource, error)
TokenSource returns the underlying token source.
type ExecTokenSource ¶
type ExecTokenSource struct {
// contains filtered or unexported fields
}
ExecTokenSource is an oauth2.TokenSource that runs an external command to mint a bearer token, caching it until shortly before it expires. It is safe for concurrent use.
func NewExecTokenSource ¶
NewExecTokenSource returns a token source that runs argv to obtain tokens. ttl caps how long an opaque (non-JWT) token is cached; for JWTs the "exp" claim takes precedence. ctx bounds the lifetime of all invocations.
func (*ExecTokenSource) Invalidate ¶
func (s *ExecTokenSource) Invalidate()
Invalidate drops the cached token so the next Token call re-runs the command.
type OAuthOptions ¶
type OAuthOptions struct {
// Label identifies the backend in prompts and logs.
Label string
// Scopes optionally restricts the OAuth scopes: the advertised scope for
// dynamic registration, and an allowlist filtering the server's advertised
// scopes for the auth-code flow. Empty requests whatever the server offers.
Scopes []string
// ClientName is the DCR client_name presented to the user (default "mcpmux").
ClientName string
// OpenBrowser controls whether the auth URL is launched automatically. The
// URL is always printed regardless, so headless/SSH use still works.
OpenBrowser bool
// CallbackPort fixes the loopback callback port; 0 picks an ephemeral one.
CallbackPort int
// ClientID/ClientSecret select a pre-registered ("confidential") client
// instead of dynamic client registration, for servers that don't support
// DCR. ClientSecret may be empty for a pre-registered public client.
ClientID string
ClientSecret string
// AllowIssuerMismatch tolerates an authorization server whose metadata
// declares an issuer different from the URL it is served from (RFC 8414
// §3.3 violation), by normalizing the issuer client-side. Needed for Slack.
AllowIssuerMismatch bool
}
OAuthOptions configures the interactive (authorization-code + PKCE) OAuth flow for a backend. The client is registered dynamically (RFC 7591).