Documentation
¶
Overview ¶
Package oauthflow implements the client side of the OAuth 2.0 authorization-code flow used to authenticate against remote MCP servers: PKCE and state generation, the loopback callback server, dynamic client registration, and code/refresh token exchange.
It is deliberately separate from pkg/tools/mcp so that packages which only drive the flow (e.g. pkg/runtime's remote-runtime login) don't link the whole MCP toolset - and everything it drags in - into embedders' binaries.
Index ¶
- func BuildAuthorizationURL(authEndpoint, clientID, redirectURI, state, codeChallenge, resourceURL string, ...) string
- func DefaultHTTPClient() *http.Client
- func GeneratePKCEVerifier() string
- func GenerateState() (string, error)
- func HTTPClientForAllowPrivateIPs(allowPrivateIPs bool) *http.Client
- func RegisterClient(ctx context.Context, authMetadata *AuthorizationServerMetadata, ...) (clientID, clientSecret, authMethod string, err error)
- func RegisterClientWithClient(ctx context.Context, client *http.Client, ...) (clientID, clientSecret, authMethod string, err error)
- func RequestAuthorizationCode(ctx context.Context, port int, prepare PrepareAuthorization) (string, string, error)
- func RequestAuthorizationCodeOnListenerForTesting(ctx context.Context, listener net.Listener, prepare PrepareAuthorization) (string, string, error)
- func SetBrowserOpenerForTesting(opener BrowserOpener) (restore func())
- func SetHTTPClientForTesting(c *http.Client) (restore func())
- type AuthorizationRequest
- type AuthorizationServerMetadata
- type BrowserOpener
- type CallbackAddress
- type OAuthToken
- func ExchangeCodeForToken(ctx context.Context, ...) (*OAuthToken, error)
- func ExchangeCodeForTokenWithClient(ctx context.Context, client *http.Client, ...) (*OAuthToken, error)
- func ExchangeCodeForTokenWithResource(ctx context.Context, ...) (*OAuthToken, error)
- func RefreshAccessToken(ctx context.Context, ...) (*OAuthToken, error)
- func RefreshAccessTokenWithClient(ctx context.Context, client *http.Client, ...) (*OAuthToken, error)
- type PrepareAuthorization
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildAuthorizationURL ¶
func BuildAuthorizationURL(authEndpoint, clientID, redirectURI, state, codeChallenge, resourceURL string, scopes []string) string
BuildAuthorizationURL builds the OAuth authorization URL with PKCE. It merges the OAuth parameters into any query string already present on authEndpoint (e.g. Grafana Cloud's grafana_url= selector) so the result always has exactly one '?' even when the endpoint carries pre-existing params.
func DefaultHTTPClient ¶
DefaultHTTPClient returns the shared SSRF-safe client used for OAuth requests that don't carry per-server header or private-IP policies.
func GeneratePKCEVerifier ¶
func GeneratePKCEVerifier() string
GeneratePKCEVerifier generates a PKCE code verifier using oauth2 library
func GenerateState ¶
GenerateState generates a random state parameter for OAuth CSRF protection
func HTTPClientForAllowPrivateIPs ¶
HTTPClientForAllowPrivateIPs returns the shared SSRF-safe client, or a variant that may reach private IPs when allowPrivateIPs is set (used by configurations that explicitly opt in to talking to a server on a private network).
func RegisterClient ¶
func RegisterClient(ctx context.Context, authMetadata *AuthorizationServerMetadata, redirectURI string, scopes []string) (clientID, clientSecret, authMethod string, err error)
RegisterClient performs dynamic client registration
func RegisterClientWithClient ¶
func RegisterClientWithClient(ctx context.Context, client *http.Client, authMetadata *AuthorizationServerMetadata, redirectURI string, scopes []string) (clientID, clientSecret, authMethod string, err error)
RegisterClientWithClient is RegisterClient with an explicit *http.Client. authMethod is the token endpoint auth method to use afterwards. A response that omits token_endpoint_auth_method is client_secret_basic (RFC 7591), not confirmation of the method we asked for.
func RequestAuthorizationCode ¶
func RequestAuthorizationCode(ctx context.Context, port int, prepare PrepareAuthorization) (string, string, error)
RequestAuthorizationCode binds the requested loopback port (0 selects a free port), prepares authorization, opens the browser and waits for the callback. All listener, serving and request-handler resources are joined before return.
func RequestAuthorizationCodeOnListenerForTesting ¶ added in v1.153.0
func RequestAuthorizationCodeOnListenerForTesting(ctx context.Context, listener net.Listener, prepare PrepareAuthorization) (string, string, error)
RequestAuthorizationCodeOnListenerForTesting transfers a reserved loopback listener into the flow without a close/rebind race. Never use in production.
func SetBrowserOpenerForTesting ¶ added in v1.125.0
func SetBrowserOpenerForTesting(opener BrowserOpener) (restore func())
SetBrowserOpenerForTesting replaces the browser opener and returns a function restoring the previous one. It exists only so tests can intercept the authorization URL without launching a real browser (and without relying on host-OS launchers). Never call it in production code.
func SetHTTPClientForTesting ¶
SetHTTPClientForTesting replaces the shared OAuth client and returns a function restoring the previous one. It exists only so tests can hit httptest servers, which bind to 127.0.0.1 — an address the SSRF-safe client refuses by design. Never call it in production code.
Types ¶
type AuthorizationRequest ¶ added in v1.153.0
AuthorizationRequest is prepared after the callback endpoint is bound.
type AuthorizationServerMetadata ¶
type AuthorizationServerMetadata struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
RevocationEndpoint string `json:"revocation_endpoint,omitempty"`
IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`
JwksURI string `json:"jwks_uri,omitempty"`
ScopesSupported []string `json:"scopes_supported,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported"`
ResponseModesSupported []string `json:"response_modes_supported,omitempty"`
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"`
RevocationEndpointAuthMethodsSupported []string `json:"revocation_endpoint_auth_methods_supported,omitempty"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"`
}
AuthorizationServerMetadata represents OAuth 2.0 Authorization Server Metadata (RFC 8414)
type BrowserOpener ¶ added in v1.125.0
BrowserOpener opens urlToOpen in the user's default browser. It is the seam through which RequestAuthorizationCode delivers the authorization URL; tests replace it to capture the URL without launching a real browser.
type CallbackAddress ¶ added in v1.153.0
type CallbackAddress struct {
// contains filtered or unexported fields
}
CallbackAddress describes the bound loopback endpoint for one authorization. It contains no server resources and may be retained after the flow returns.
func (CallbackAddress) Port ¶ added in v1.153.0
func (a CallbackAddress) Port() int
func (CallbackAddress) RedirectURI ¶ added in v1.153.0
func (a CallbackAddress) RedirectURI() string
func (CallbackAddress) ResolveRedirectURI ¶ added in v1.153.0
func (a CallbackAddress) ResolveRedirectURI(override string) string
ResolveRedirectURI substitutes the bound port without rewriting the override.
type OAuthToken ¶
type OAuthToken struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
AuthServer string `json:"auth_server,omitempty"`
// TokenEndpointAuthMethod is the RFC 7591 method agreed at registration.
// Empty means client_secret_post, which is what tokens stored before
// this field used.
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
// RequestedScopes records the scope list actually requested when this
// token was obtained: the configured scopes, or — on a successful
// dynamic client registration with no configured override — the
// challenge- or protected-resource-metadata-derived scopes selected by
// selectDCRScopes. Unlike Scope (which is whatever the authorization
// server chose to return, sometimes empty, sometimes comma/space
// separated), RequestedScopes reflects our intent and is used to detect
// when the config has changed and a new OAuth flow is required.
RequestedScopes []string `json:"requested_scopes,omitempty"`
}
OAuthToken is an OAuth 2.0 access token together with the refresh token, client credentials and scope bookkeeping needed to refresh it later.
func ExchangeCodeForToken ¶
func ExchangeCodeForToken(ctx context.Context, tokenEndpoint, code, codeVerifier, clientID, clientSecret, redirectURI string) (*OAuthToken, error)
ExchangeCodeForToken exchanges an authorization code for an access token.
func ExchangeCodeForTokenWithClient ¶
func ExchangeCodeForTokenWithClient(ctx context.Context, client *http.Client, tokenEndpoint, code, codeVerifier, clientID, clientSecret, redirectURI, resourceURL, authMethod string) (*OAuthToken, error)
ExchangeCodeForTokenWithClient is ExchangeCodeForTokenWithResource with an explicit *http.Client, for callers that layer per-server headers or private-IP policies on top of the default client.
func ExchangeCodeForTokenWithResource ¶
func ExchangeCodeForTokenWithResource(ctx context.Context, tokenEndpoint, code, codeVerifier, clientID, clientSecret, redirectURI, resourceURL string) (*OAuthToken, error)
ExchangeCodeForTokenWithResource exchanges an authorization code and sends the RFC 8707 resource indicator to token endpoints that require it.
func RefreshAccessToken ¶
func RefreshAccessToken(ctx context.Context, tokenEndpoint, refreshToken, clientID, clientSecret string) (*OAuthToken, error)
RefreshAccessToken uses a refresh token to obtain a new access token without user interaction.
func RefreshAccessTokenWithClient ¶
func RefreshAccessTokenWithClient(ctx context.Context, client *http.Client, tokenEndpoint, refreshToken, clientID, clientSecret, authMethod string) (*OAuthToken, error)
RefreshAccessTokenWithClient is RefreshAccessToken with an explicit *http.Client.
func (*OAuthToken) IsExpired ¶
func (t *OAuthToken) IsExpired() bool
IsExpired checks if the token is expired
type PrepareAuthorization ¶ added in v1.153.0
type PrepareAuthorization func(ctx context.Context, address CallbackAddress) (AuthorizationRequest, error)
PrepareAuthorization resolves credentials and builds the authorization URL. It runs synchronously and must honor ctx, including when serving fails.