Documentation
¶
Index ¶
- func AccessTokenFromContext(ctx context.Context) (string, bool)
- func ValidatePKCE(verifier, challenge, method string) bool
- func WithAccessToken(ctx context.Context, token string) context.Context
- func WithTokenInfo(ctx context.Context, info *IntrospectionResponse) context.Context
- type AuthorizationCode
- type ExternalToken
- type GenericProvider
- func (p *GenericProvider) BuildAuthURL(callbackURL, state string) (string, error)
- func (p *GenericProvider) ExchangeCode(ctx context.Context, code, callbackURL string) (*ExternalToken, error)
- func (p *GenericProvider) IntrospectToken(ctx context.Context, token string) (*IntrospectionResponse, error)
- func (p *GenericProvider) RefreshToken(ctx context.Context, refreshToken string) (*ExternalToken, error)
- type IntrospectionResponse
- type Middleware
- type OAuthClient
- type OAuthConfig
- type OAuthServer
- func (s *OAuthServer) HandleAuthorize(w http.ResponseWriter, r *http.Request)
- func (s *OAuthServer) HandleCallback(w http.ResponseWriter, r *http.Request)
- func (s *OAuthServer) HandleComplete(w http.ResponseWriter, r *http.Request)
- func (s *OAuthServer) HandleRegister(w http.ResponseWriter, r *http.Request)
- func (s *OAuthServer) HandleToken(w http.ResponseWriter, r *http.Request)
- type OAuthStore
- func (s *OAuthStore) Close()
- func (s *OAuthStore) ConsumeCode(code string) (*AuthorizationCode, bool)
- func (s *OAuthStore) ConsumeCompletion(token string) (string, bool)
- func (s *OAuthStore) ConsumePending(csrfToken string) (*PendingAuthorization, bool)
- func (s *OAuthStore) CreateClient(redirectURIs, grantTypes, responseTypes []string, authMethod string) *OAuthClient
- func (s *OAuthStore) GetClient(clientID string) (*OAuthClient, bool)
- func (s *OAuthStore) StoreCode(code *AuthorizationCode)
- func (s *OAuthStore) StoreCompletion(redirectURL string) string
- func (s *OAuthStore) StorePending(pa *PendingAuthorization)
- type PendingAuthorization
- type Provider
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AccessTokenFromContext ¶
AccessTokenFromContext retrieves the raw OAuth access token string stored by the auth middleware.
func ValidatePKCE ¶
ValidatePKCE verifies that a code_verifier matches the stored code_challenge using the S256 method (SHA256 + base64url without padding) per RFC 7636.
func WithAccessToken ¶
WithAccessToken stores the raw OAuth access token in the given context.
func WithTokenInfo ¶
func WithTokenInfo(ctx context.Context, info *IntrospectionResponse) context.Context
WithTokenInfo stores the IntrospectionResponse in the given context.
Types ¶
type AuthorizationCode ¶
type AuthorizationCode struct {
Code string
ClientID string
RedirectURI string
CodeChallenge string
ChallengeMethod string
ExpiresAt time.Time
ExternalToken *ExternalToken
}
AuthorizationCode is created after successful authentication and holds the external token for exchange via the token endpoint.
type ExternalToken ¶
type ExternalToken struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token,omitempty"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in,omitempty"`
Scope string `json:"scope,omitempty"`
}
ExternalToken holds the token received from the upstream SSO provider.
type GenericProvider ¶
type GenericProvider struct {
// contains filtered or unexported fields
}
GenericProvider implements the Provider interface for standard OAuth 2.0 / OIDC identity providers (Keycloak, Red Hat SSO, Okta, Azure AD, etc.). It uses the Authorization Code flow with token introspection (RFC 7662).
func NewGenericProvider ¶
func NewGenericProvider(cfg *OAuthConfig) (*GenericProvider, error)
NewGenericProvider creates a provider from an OAuthConfig. Requires: ClientID, ClientSecret, AuthorizationURL, TokenURL, IntrospectionURL.
func (*GenericProvider) BuildAuthURL ¶
func (p *GenericProvider) BuildAuthURL(callbackURL, state string) (string, error)
func (*GenericProvider) ExchangeCode ¶
func (p *GenericProvider) ExchangeCode(ctx context.Context, code, callbackURL string) (*ExternalToken, error)
func (*GenericProvider) IntrospectToken ¶
func (p *GenericProvider) IntrospectToken(ctx context.Context, token string) (*IntrospectionResponse, error)
func (*GenericProvider) RefreshToken ¶
func (p *GenericProvider) RefreshToken(ctx context.Context, refreshToken string) (*ExternalToken, error)
type IntrospectionResponse ¶
type IntrospectionResponse struct {
Active bool `json:"active"`
Sub string `json:"sub,omitempty"`
ClientID string `json:"client_id,omitempty"`
Username string `json:"username,omitempty"`
TokenType string `json:"token_type,omitempty"`
Exp int64 `json:"exp,omitempty"`
Iat int64 `json:"iat,omitempty"`
Iss string `json:"iss,omitempty"`
Scope string `json:"scope,omitempty"`
}
IntrospectionResponse represents the OAuth 2.0 Token Introspection response per RFC 7662.
func TokenInfoFromContext ¶
func TokenInfoFromContext(ctx context.Context) (*IntrospectionResponse, bool)
TokenInfoFromContext retrieves the IntrospectionResponse stored by the auth middleware.
type Middleware ¶
type Middleware struct {
// contains filtered or unexported fields
}
Middleware validates OAuth Bearer tokens using a Provider for introspection.
func NewMiddleware ¶
func NewMiddleware(provider Provider, logger *slog.Logger) *Middleware
NewMiddleware creates a new OAuth middleware that validates tokens by delegating introspection to the given Provider.
func (*Middleware) Authenticate ¶
func (m *Middleware) Authenticate(next http.Handler) http.Handler
Authenticate returns HTTP middleware that validates OAuth Bearer tokens. Validated token info is stored in the request context and accessible via TokenInfoFromContext.
func (*Middleware) Close ¶
func (m *Middleware) Close()
Close stops the background cache cleanup goroutine.
func (*Middleware) MetadataHandler ¶
func (*Middleware) MetadataHandler() http.HandlerFunc
MetadataHandler serves OAuth Authorization Server Metadata (RFC 8414). All endpoints point to our server, which proxies authentication to the external SSO.
func (*Middleware) ProtectedResourceMetadataHandler ¶
func (*Middleware) ProtectedResourceMetadataHandler() http.HandlerFunc
ProtectedResourceMetadataHandler serves OAuth Protected Resource Metadata (RFC 9728) at /.well-known/oauth-protected-resource. MCP clients use this to discover which authorization server to use for obtaining tokens.
type OAuthClient ¶
type OAuthClient struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RedirectURIs []string `json:"redirect_uris"`
GrantTypes []string `json:"grant_types"`
ResponseTypes []string `json:"response_types"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method"`
}
OAuthClient represents a dynamically registered OAuth client (RFC 7591).
type OAuthConfig ¶
type OAuthConfig struct {
ClientID string
ClientSecret string
AuthorizationURL string
TokenURL string
IntrospectionURL string
CallbackURL string
}
OAuthConfig holds OAuth configuration loaded from environment variables.
func NewOAuthConfigFromEnv ¶
func NewOAuthConfigFromEnv() (*OAuthConfig, error)
NewOAuthConfigFromEnv creates an OAuthConfig from SSO_* environment variables.
type OAuthServer ¶
type OAuthServer struct {
// contains filtered or unexported fields
}
OAuthServer implements the OAuth 2.1 Authorization Server endpoints that proxy authentication to an external provider via the Provider interface. MCP clients interact with these endpoints; actual user authentication is delegated to the Provider.
func NewOAuthServer ¶
func NewOAuthServer(provider Provider, callbackURL string, store *OAuthStore, logger *slog.Logger) *OAuthServer
NewOAuthServer creates a new OAuth authorization server. callbackURL is our server's /auth/callback/oidc endpoint URL that the external SSO will redirect to after user authentication.
func (*OAuthServer) HandleAuthorize ¶
func (s *OAuthServer) HandleAuthorize(w http.ResponseWriter, r *http.Request)
HandleAuthorize implements the Authorization Endpoint (RFC 6749 Section 3.1). Validates the request, stores a pending authorization with a CSRF token, then redirects to the external provider for user authentication. The authorization code is only generated after successful authentication in HandleCallback. GET /auth/authorize
func (*OAuthServer) HandleCallback ¶
func (s *OAuthServer) HandleCallback(w http.ResponseWriter, r *http.Request)
HandleCallback handles the redirect from the external provider after user authentication. It verifies the CSRF token, exchanges the provider's code for a token, generates an authorization code, and redirects back to the MCP client. GET /auth/callback/oidc
func (*OAuthServer) HandleComplete ¶
func (s *OAuthServer) HandleComplete(w http.ResponseWriter, r *http.Request)
HandleComplete serves the post-authentication success page at a clean URL with no OAuth parameters exposed. It renders a meta-refresh redirect to the MCP client's redirect_uri. GET /auth/complete/{token}
func (*OAuthServer) HandleRegister ¶
func (s *OAuthServer) HandleRegister(w http.ResponseWriter, r *http.Request)
HandleRegister implements Dynamic Client Registration (RFC 7591). POST /auth/register
func (*OAuthServer) HandleToken ¶
func (s *OAuthServer) HandleToken(w http.ResponseWriter, r *http.Request)
HandleToken implements the Token Endpoint (RFC 6749 Section 3.2). Supports authorization_code (with PKCE) and refresh_token grant types. POST /auth/token
type OAuthStore ¶
type OAuthStore struct {
// contains filtered or unexported fields
}
OAuthStore provides in-memory storage for OAuth clients, pending authorizations, authorization codes, and completion redirects.
func NewOAuthStore ¶
func NewOAuthStore() *OAuthStore
NewOAuthStore creates a new in-memory OAuth store with a background cleanup goroutine that evicts expired pending authorizations and codes.
func (*OAuthStore) Close ¶
func (s *OAuthStore) Close()
Close stops the background cleanup goroutine.
func (*OAuthStore) ConsumeCode ¶
func (s *OAuthStore) ConsumeCode(code string) (*AuthorizationCode, bool)
ConsumeCode atomically retrieves and removes an authorization code (single-use). Returns nil if the code is invalid, expired, or already consumed.
func (*OAuthStore) ConsumeCompletion ¶
func (s *OAuthStore) ConsumeCompletion(token string) (string, bool)
ConsumeCompletion atomically retrieves and removes a completion redirect URL.
func (*OAuthStore) ConsumePending ¶
func (s *OAuthStore) ConsumePending(csrfToken string) (*PendingAuthorization, bool)
ConsumePending atomically retrieves and removes a pending authorization.
func (*OAuthStore) CreateClient ¶
func (s *OAuthStore) CreateClient(redirectURIs, grantTypes, responseTypes []string, authMethod string) *OAuthClient
CreateClient registers a new OAuth client with generated credentials.
func (*OAuthStore) GetClient ¶
func (s *OAuthStore) GetClient(clientID string) (*OAuthClient, bool)
GetClient retrieves a registered client by ID.
func (*OAuthStore) StoreCode ¶
func (s *OAuthStore) StoreCode(code *AuthorizationCode)
StoreCode saves an authorization code for later exchange.
func (*OAuthStore) StoreCompletion ¶
func (s *OAuthStore) StoreCompletion(redirectURL string) string
StoreCompletion saves a redirect URL keyed by a short-lived token. Used to redirect from the callback to a clean URL before showing the success page.
func (*OAuthStore) StorePending ¶
func (s *OAuthStore) StorePending(pa *PendingAuthorization)
StorePending saves a pending authorization keyed by its CSRF token.
type PendingAuthorization ¶
type PendingAuthorization struct {
CSRFToken string
ClientID string
RedirectURI string
CodeChallenge string
ChallengeMethod string
OrigState string
ExpiresAt time.Time
}
PendingAuthorization holds context for an in-flight OAuth authorize request. Keyed by CSRF token in the store; consumed when the SSO callback arrives.
type Provider ¶
type Provider interface {
// BuildAuthURL constructs the external authorization URL to redirect the user to.
// callbackURL is our server's /auth/callback/oidc endpoint.
// state is an opaque value passed through the redirect round-trip.
BuildAuthURL(callbackURL, state string) (string, error)
// ExchangeCode trades an authorization code received from the external provider
// for an access token (and optionally a refresh token).
ExchangeCode(ctx context.Context, code, callbackURL string) (*ExternalToken, error)
// RefreshToken obtains a new access token using a refresh token.
RefreshToken(ctx context.Context, refreshToken string) (*ExternalToken, error)
// IntrospectToken validates an access token and returns its metadata.
// Implementations may call an introspection endpoint (RFC 7662) or use
// provider-specific validation (e.g. Google's tokeninfo).
IntrospectToken(ctx context.Context, token string) (*IntrospectionResponse, error)
}
Provider abstracts the upstream OAuth identity provider. Each implementation (generic OIDC, Google, etc.) handles the provider-specific details of building auth URLs, exchanging codes, refreshing tokens, and introspecting tokens.
The OAuthServer and Middleware are provider-agnostic — they delegate all provider-specific work through this interface.