Help us shape the future of Go! Take the 2026 Go Developer Survey

oauthflow

package
v1.154.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

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

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

func DefaultHTTPClient() *http.Client

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

func GenerateState() (string, error)

GenerateState generates a random state parameter for OAuth CSRF protection

func HTTPClientForAllowPrivateIPs

func HTTPClientForAllowPrivateIPs(allowPrivateIPs bool) *http.Client

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

func SetHTTPClientForTesting(c *http.Client) (restore func())

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

type AuthorizationRequest struct {
	URL   string
	State string
}

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

type BrowserOpener func(ctx context.Context, urlToOpen string) error

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.

Jump to

Keyboard shortcuts

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