oauth

package module
v1.0.10 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2026 License: Apache-2.0 Imports: 11 Imported by: 2

README

mcp-oauth

A provider-agnostic OAuth 2.1 Authorization Server library for Model Context Protocol (MCP) servers, with support for multiple identity providers.

MCP Specification Compliance

Specification Version Support Status Documentation
2025-11-25 Full Support Migration Guide
2025-06-18 (previous) Full Support Backward compatible

Key Features

  • Provider Abstraction - Google, GitHub, and Dex OAuth built-in, easy to add custom providers
  • Storage Abstraction - In-memory storage included, simple interface for custom backends
  • OAuth 2.1 Security - PKCE enforcement, refresh token rotation, secure defaults
  • Access Token Formats - Opaque (default) or signed JWT (RFC 9068) with published JWKS for local validation by MCP-aware proxies
  • MCP 2025-11-25 - Protected Resource Metadata (RFC 9728), scope discovery, resource binding
  • Silent Authentication - OIDC prompt parameter support for seamless token refresh without user interaction
  • Client ID Metadata Documents - URL-based client IDs with dynamic metadata discovery
  • Lifecycle Callbacks - Session creation, revocation, and token refresh event hooks
  • Observability - OpenTelemetry instrumentation with Prometheus and OTLP support

Architecture

┌─────────────────┐
│   Your MCP App  │
└────────┬────────┘
         │
    ┌────▼─────┐
    │ Handler  │  HTTP layer
    └────┬─────┘
         │
    ┌────▼─────┐
    │  Server  │  Business logic
    └──┬───┬───┘
       │   │
   ┌───▼┐ ┌▼────────┐
   │Pro-│ │ Storage │
   │vider│ │         │
   └────┘ └─────────┘
  • Handler: HTTP request/response handling
  • Server: OAuth business logic (provider-agnostic)
  • Provider: Identity provider integration (Google, GitHub, Dex, or custom)
  • Storage: Token/client/flow persistence

Quick Start

package main

import (
    "net/http"
    "os"

    oauth "github.com/giantswarm/mcp-oauth"
    "github.com/giantswarm/mcp-oauth/handler"
    "github.com/giantswarm/mcp-oauth/providers/google"
    "github.com/giantswarm/mcp-oauth/storage/memory"
)

func main() {
    // 1. Choose a provider
    provider, _ := google.NewProvider(&google.Config{
        ClientID:     os.Getenv("GOOGLE_CLIENT_ID"),
        ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"),
        RedirectURL:  "http://localhost:8080/oauth/callback",
        Scopes:       []string{"openid", "email", "profile"},
    })

    // 2. Choose storage
    store := memory.New()
    defer store.Stop()

    // 3. Create OAuth server
    server, _ := oauth.NewServer(
        provider,
        store, // TokenStore
        store, // ClientStore
        store, // FlowStore
        &oauth.ServerConfig{
            Issuer: "http://localhost:8080",
        },
        nil,
    )

    // 4. Create HTTP handler and routes
    h := handler.New(server, nil)
    mux := http.NewServeMux()

    h.RegisterProtectedResourceMetadataRoutes(mux, "/mcp")
    mux.Handle("/mcp", h.ValidateToken(yourMCPHandler))

    http.ListenAndServe(":8080", mux)
}

Installation

go get github.com/giantswarm/mcp-oauth

Documentation

Document Description
Getting Started Installation, providers, storage, first OAuth server
Configuration All configuration options, CORS, interstitial pages, proxy settings
Security Guide Security features, best practices, production checklist
Observability OpenTelemetry, Prometheus metrics, distributed tracing
Discovery Mechanisms OAuth discovery (RFC 8414, RFC 9728)
MCP 2025-11-25 New specification features and migration
Silent Authentication OIDC prompt parameter for seamless re-authentication
Client ID Metadata Documents URL-based client IDs with dynamic metadata discovery
DPoP (RFC 9449) Sender-constraint setup, middleware wiring, multi-pod replay cache
Token Exchange (RFC 8693) Service-to-service and Kubernetes SA token exchange
Client Management (RFC 7592) Per-client read/update/delete for dynamically registered clients
Security Architecture Deep-dive into security implementation

Examples

The examples/ directory contains runnable examples:

  • basic - Minimal setup with Google
  • github - GitHub OAuth with organization restriction
  • dex - Dex provider with connector_id and groups support
  • production - Full security features
  • custom-scopes - Endpoint-specific scope requirements
  • mcp-2025-11-25 - New MCP specification features
  • cimd - Client ID Metadata Documents (URL-based client IDs)
  • prometheus - Observability integration

Security

This library implements OAuth 2.1 with secure defaults:

  • PKCE required (S256 only)
  • Refresh token rotation with reuse detection
  • Token encryption at rest (AES-256-GCM)
  • Rate limiting and audit logging
Secret Management (CRITICAL for Production)

NEVER use environment variables for production secrets!

Production deployments MUST use a secret manager:

  • HashiCorp Vault (recommended for Kubernetes)
  • AWS Secrets Manager (for AWS deployments)
  • Google Cloud Secret Manager (for GCP deployments)
  • Azure Key Vault (for Azure deployments)

NEVER:

  • Use environment variables for secrets in production
  • Hardcode secrets in code or configuration files
  • Commit secrets to version control
  • Store secrets in container images or Dockerfiles

See Production Example - Secret Management for implementation guidance and examples.

Documentation

See the Security Guide for configuration and the Security Architecture for implementation details.

Vulnerability Reporting: See SECURITY.md for responsible disclosure.

Contributing

Contributions welcome. Especially:

  • New provider implementations
  • Storage backends
  • Security enhancements

See CONTRIBUTING.md for guidelines.

License

Apache License 2.0

Documentation

Overview

Package oauth provides an OAuth 2.1 / OIDC authorization server library intended to back an MCP server, aligned with the MCP 2025-11-25 OAuth profile. It implements the Protected-Resource role (token validation + metadata) and the Authorization-Server role (authorize / token / revoke / introspect / register / userinfo / discovery endpoints).

Architecture

The package is split into:

Security defaults

Library defaults aim for spec-compliant secure-by-default behaviour:

  • PKCE required; only S256 accepted (RFC 7636 + OAuth 2.1).
  • Refresh-token rotation on; reuse detection revokes the family.
  • `state` parameter required and length-bounded (configurable via server.Config.MinStateLength / server.Config.MaxStateLength).
  • Per-IP and per-user rate limiters guard hot endpoints.
  • Bearer-token comparisons are constant-time.
  • Token-at-rest encryption available via security.NewEncryptor + [memory.WithEncryptor] / [valkey.WithEncryptor]; the ciphertext envelope is versioned with a 1-byte `kid` for future rotation.
  • OIDC `nonce` is required end-to-end when scoped `openid` (CWE-294).
  • SSRF protection on the client-metadata-document and discovery fetchers.

Insecure opt-outs (e.g. server.Config.AllowNoStateParameter, server.Config.AllowInsecureHTTP) emit a startup WARN.

Compliance

Implemented:

  • RFC 6749 (OAuth 2.0 / OAuth 2.1 draft)
  • RFC 6750 (Bearer token usage + WWW-Authenticate)
  • RFC 7009 (Token revocation)
  • RFC 7517 / 7518 / 7519 (JWS / JWA / JWT) via go-jose/v4
  • RFC 7591 (Dynamic Client Registration; response includes `client_id_issued_at`, `client_secret_expires_at`)
  • RFC 7636 (PKCE — S256 only)
  • RFC 7662 (Token introspection §2.2 shape + cross-client gate)
  • RFC 8414 (Authorization Server Metadata + Cache-Control)
  • RFC 8707 (Resource indicators + audience binding)
  • RFC 9068 (JWT-profile access tokens)
  • RFC 9207 (`iss` response parameter)
  • RFC 9728 (Protected Resource Metadata)
  • OIDC Core 1.0 §3 + §5.3 (`/userinfo`)
  • OIDC Discovery 1.0 §3 (subject_types_supported, id_token_signing_alg_values_supported, claims_supported)

Example

A minimal in-memory server using the Google provider, encryption-at-rest from environment, and the standard `OAUTH_*` env loader. See the `examples/` directory for full end-to-end programs.

package main

import (
	"log"
	"log/slog"
	"net/http"
	"os"

	"github.com/giantswarm/mcp-oauth/handler"
	"github.com/giantswarm/mcp-oauth/oauthconfig"
	"github.com/giantswarm/mcp-oauth/providers/google"
	"github.com/giantswarm/mcp-oauth/server"
	"github.com/giantswarm/mcp-oauth/storage/memory"
)

func main() {
	cfg, err := oauthconfig.FromEnv()
	if err != nil {
		log.Fatal(err)
	}

	enc, err := oauthconfig.NewEncryptorFromEnv()
	if err != nil {
		log.Fatal(err)
	}

	provider, err := google.NewProvider(&google.Config{
		ClientID:     os.Getenv("GOOGLE_CLIENT_ID"),
		ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"),
		RedirectURL:  cfg.Issuer + "/oauth/callback",
	})
	if err != nil {
		log.Fatal(err)
	}

	store := memory.New(memory.WithEncryptor(enc))
	srv, err := server.New(provider, store, store, store, cfg, slog.Default())
	if err != nil {
		log.Fatal(err)
	}

	h := handler.New(srv, slog.Default())

	mux := http.NewServeMux()
	h.RegisterOAuthRoutes(mux, handler.OAuthRoutesOptions{IncludeMetadata: true})
	mux.Handle("/mcp", h.ValidateToken(mcpHandler))
	log.Fatal(http.ListenAndServe(":8080", mux))
}

The library does not provide MCP itself — `mcpHandler` is whatever your MCP transport exposes. The OAuth layer protects it via [handler.Handler.ValidateToken], which extracts the bearer token, validates it against the configured provider (or self-issued JWT in JWT-AT mode), and stashes the resolved providers.UserInfo in the request context for [handler.UserInfoFromContext].

Index

Constants

View Source
const (
	// DefaultRefreshTokenTTL is the default time-to-live for refresh tokens (90 days)
	DefaultRefreshTokenTTL = 90 * 24 * time.Hour

	// DefaultAuthorizationCodeTTL is how long authorization codes are valid (10 minutes)
	DefaultAuthorizationCodeTTL = 10 * time.Minute

	// DefaultAccessTokenTTL is the default access token expiry (1 hour)
	DefaultAccessTokenTTL = 1 * time.Hour

	// DefaultCleanupInterval is how often to cleanup expired tokens (1 minute)
	DefaultCleanupInterval = 1 * time.Minute

	// DefaultRateLimitCleanupInterval is how often to cleanup inactive rate limiters
	DefaultRateLimitCleanupInterval = 5 * time.Minute

	// InactiveLimiterCleanupWindow is the time after which inactive limiters are removed
	InactiveLimiterCleanupWindow = 10 * time.Minute

	// TokenRefreshThreshold is how soon before expiry to attempt token refresh
	TokenRefreshThreshold = 5 * time.Minute

	// TokenExpiringThreshold is the minimum time before a token is considered expiring
	TokenExpiringThreshold = 60 // seconds

	// ClockSkewGrace is the grace period (in seconds) for clock skew when
	// validating tokens this server issued — 5s handles typical NTP drift
	// without materially extending token lifetime. Upstream-issued tokens
	// (forwarded id_tokens, JWKS-verified IdP tokens) use a larger leeway
	// because cross-organisation NTP skew is harder to bound; see
	// [github.com/giantswarm/mcp-oauth/providers/oidc.DefaultClockSkewLeeway]
	// (30s).
	ClockSkewGrace = 5 // seconds
)

OAuth token and code timeouts

View Source
const (
	// DefaultMaxClientsPerIP is the default limit for client registrations per IP
	DefaultMaxClientsPerIP = 10

	// DefaultRateLimitRate is the default requests per second per IP
	DefaultRateLimitRate = 10

	// DefaultRateLimitBurst is the default burst size for rate limiting
	DefaultRateLimitBurst = 20

	// DefaultTokenEndpointAuthMethod is the default client authentication method
	DefaultTokenEndpointAuthMethod = "client_secret_basic"
)

OAuth client and security defaults

View Source
const (
	// ClientIDTokenLength is the length of generated client IDs
	ClientIDTokenLength = 32

	// ClientSecretTokenLength is the length of generated client secrets
	ClientSecretTokenLength = 48

	// AccessTokenLength is the length of generated access tokens
	AccessTokenLength = 48

	// RefreshTokenLength is the length of generated refresh tokens
	RefreshTokenLength = 48

	// StateTokenLength is the length of generated state parameters
	StateTokenLength = 32

	// MinStateLength is the minimum length for state parameters to prevent
	// timing attacks and ensure sufficient entropy for CSRF protection.
	// OAuth 2.1 recommends at least 128 bits (16 bytes) of entropy.
	// 24 characters provides 144 bits of entropy in base64, exceeding the 128-bit minimum.
	// This value is used as the default for server.Config.MinStateLength.
	MinStateLength = 24

	// MaxStateLength caps the `state` parameter length to prevent audit-log
	// inflation / DoS via oversized state values; 512 characters accommodates
	// the common JWT-encoded-state pattern (~256-380 chars).
	// This value is used as the default for server.Config.MaxStateLength.
	MaxStateLength = 512
)

PKCE and token generation constants

View Source
const (
	// ClientTypeConfidential represents a confidential OAuth client
	ClientTypeConfidential = "confidential"

	// ClientTypePublic represents a public OAuth client
	ClientTypePublic = "public"
)

OAuth client types

View Source
const (
	// TokenEndpointAuthMethodNone represents no authentication (public clients)
	TokenEndpointAuthMethodNone = "none"

	// TokenEndpointAuthMethodBasic represents HTTP Basic authentication
	TokenEndpointAuthMethodBasic = "client_secret_basic"

	// TokenEndpointAuthMethodPost represents POST form parameters
	TokenEndpointAuthMethodPost = "client_secret_post"
)

Token endpoint authentication methods (RFC 7591)

View Source
const (
	// SchemeHTTP is the HTTP URI scheme
	SchemeHTTP = "http"

	// SchemeHTTPS is the HTTPS URI scheme
	SchemeHTTPS = "https"
)

URI schemes

View Source
const (
	// MetadataPathProtectedResource is the RFC 9728 Protected Resource Metadata discovery path
	MetadataPathProtectedResource = "/.well-known/oauth-protected-resource"

	// MetadataPathAuthorizationServer is the RFC 8414 Authorization Server Metadata discovery path
	MetadataPathAuthorizationServer = "/.well-known/oauth-authorization-server"

	// MaxMetadataPathLength is the maximum allowed length for custom metadata paths
	// This prevents DoS attacks through excessively long path registration
	MaxMetadataPathLength = 256
)

OAuth discovery paths (RFC 8414, RFC 9728)

View Source
const (
	// MaxLoginHintLength is the maximum length for the login_hint parameter.
	// This is typically an email address (RFC 5321 limits to 254 chars).
	// We use 256 to accommodate edge cases and remain consistent with other ID limits.
	MaxLoginHintLength = 256

	// MaxIDTokenHintLength is the maximum length for the id_token_hint parameter.
	// JWTs can be large (especially with many claims), so we allow up to 64KB.
	// This matches maxSubjectTokenLength used in token exchange flows.
	MaxIDTokenHintLength = 64 * 1024 // 64KB

	// MaxACRValuesLength is the maximum length for the acr_values parameter.
	// ACR values are typically short URNs, but can be space-separated lists.
	MaxACRValuesLength = 1024

	// MaxPromptLength is the maximum length for the prompt parameter.
	// Valid values are "none", "login", "consent", "select_account" or combinations.
	// Even with all combined ("login consent select_account"), this is well under 100 chars.
	MaxPromptLength = 128

	// MaxMaxAgeLength is the maximum length for the max_age parameter (in seconds).
	// This caps parsing work for untrusted input.
	MaxMaxAgeLength = 10

	// MaxMaxAgeSeconds caps max_age to a reasonable window (31 days).
	// Values above this are ignored to reduce DoS risk from huge integers.
	MaxMaxAgeSeconds = 31 * 24 * 60 * 60

	// MaxNonceLength is the maximum length for the OIDC `nonce` parameter.
	MaxNonceLength = 256
)

OIDC parameter validation constants (OpenID Connect Core 1.0 Section 3.1.2.1) These limits provide defense-in-depth against DoS attacks via oversized parameters.

Variables

View Source
var (
	// DangerousSchemes lists URI schemes that must never be allowed for security
	DangerousSchemes = []string{"javascript", "data", "file", "vbscript", "about"}

	// LoopbackAddresses lists recognized loopback addresses for development
	LoopbackAddresses = []string{"localhost", "127.0.0.1", "::1", "[::1]"}
)

Redirect URI validation constants

View Source
var (
	// DefaultGrantTypes are the grant types supported by default
	DefaultGrantTypes = []string{"authorization_code", "refresh_token"}

	// DefaultResponseTypes are the response types supported by default
	DefaultResponseTypes = []string{"code"}

	// SupportedCodeChallengeMethods are the PKCE methods we support
	// Security: Only S256 is allowed. "plain" method is insecure and violates OAuth 2.1
	SupportedCodeChallengeMethods = []string{"S256"}

	// SupportedTokenAuthMethods are the supported token endpoint auth methods
	SupportedTokenAuthMethods = []string{"client_secret_basic", "client_secret_post", "none"}
)

OAuth grant types and response types

View Source
var (
	// ErrInvalidRequest indicates the request is malformed or missing required parameters
	ErrInvalidRequest = func(desc string) *Error {
		return NewError(constants.ErrorCodeInvalidRequest, desc, http.StatusBadRequest)
	}

	// ErrInvalidGrant indicates the authorization code or refresh token is invalid or expired
	ErrInvalidGrant = func(desc string) *Error {
		return NewError(constants.ErrorCodeInvalidGrant, desc, http.StatusBadRequest)
	}

	// ErrInvalidClient indicates client authentication failed
	ErrInvalidClient = func(desc string) *Error {
		return NewError(constants.ErrorCodeInvalidClient, desc, http.StatusUnauthorized)
	}

	// ErrInvalidScope indicates the requested scope is invalid or unsupported
	ErrInvalidScope = func(desc string) *Error {
		return NewError(constants.ErrorCodeInvalidScope, desc, http.StatusBadRequest)
	}

	// ErrInvalidToken indicates the access token is invalid or expired
	ErrInvalidToken = func(desc string) *Error {
		return NewError(constants.ErrorCodeInvalidToken, desc, http.StatusUnauthorized)
	}

	// ErrInsufficientScope indicates the access token lacks required scopes
	ErrInsufficientScope = func(desc string) *Error {
		return NewError(constants.ErrorCodeInsufficientScope, desc, http.StatusForbidden)
	}

	// ErrUnauthorizedClient indicates the client is not authorized for the requested grant type
	ErrUnauthorizedClient = func(desc string) *Error {
		return NewError(constants.ErrorCodeUnauthorizedClient, desc, http.StatusBadRequest)
	}

	// ErrUnsupportedGrantType indicates the grant type is not supported
	ErrUnsupportedGrantType = func(desc string) *Error {
		return NewError(constants.ErrorCodeUnsupportedGrantType, desc, http.StatusBadRequest)
	}

	// ErrServerError indicates an internal server error occurred
	ErrServerError = func(desc string) *Error {
		return NewError(constants.ErrorCodeServerError, desc, http.StatusInternalServerError)
	}

	// ErrAccessDenied indicates the user or authorization server denied the request
	ErrAccessDenied = func(desc string) *Error {
		return NewError(constants.ErrorCodeAccessDenied, desc, http.StatusForbidden)
	}

	// ErrInvalidRedirectURI indicates the redirect URI is invalid or not registered
	ErrInvalidRedirectURI = func(desc string) *Error {
		return NewError(constants.ErrorCodeInvalidRedirectURI, desc, http.StatusBadRequest)
	}
)

Common OAuth errors as reusable instances

View Source
var ErrSilentAuthFailed = errors.New("silent authentication failed: user interaction required")

ErrSilentAuthFailed is a sentinel error for when silent authentication is not possible. This occurs when the IdP requires user interaction (login or consent) but the authorization request used prompt=none for silent authentication.

Use IsSilentAuthError to check if an error indicates silent auth failure.

View Source
var ErrTrustedAudienceMismatch = server.ErrTrustedAudienceMismatch

ErrTrustedAudienceMismatch is returned by [Server.AcceptForwardedIDToken] when the bearer token's `aud` claim does not match any entry in Config.TrustedAudiences. Callers typically respond with 401.

View Source
var NewOAuthError = NewError

NewOAuthError is an alias for NewError, provided for backward compatibility.

Deprecated: Use NewError instead. This alias will be removed in a future major version.

Functions

func IsSilentAuthError added in v0.2.46

func IsSilentAuthError(err error) bool

IsSilentAuthError returns true if the error indicates silent authentication failed and interactive login is required. This checks for:

  • *SilentAuthError type (including wrapped errors)
  • Error strings containing known silent auth error codes

Example usage:

result := handleCallback(r)
if err := result.Err(); err != nil {
    if oauth.IsSilentAuthError(err) {
        // Fall back to interactive login
        return startInteractiveLogin(w, r)
    }
    // Handle other errors
    return handleError(w, err)
}

func ParseOAuthError added in v0.2.46

func ParseOAuthError(errorCode, errorDescription string) error

ParseOAuthError parses an OAuth error response and returns the appropriate error type. For silent auth failure codes (login_required, consent_required, interaction_required, account_selection_required), returns a *SilentAuthError. For other errors, returns a generic *Error with the code and description. Returns nil if errorCode is empty.

Example usage:

err := oauth.ParseOAuthError(r.URL.Query().Get("error"), r.URL.Query().Get("error_description"))
if err != nil {
    if oauth.IsSilentAuthError(err) {
        // Handle silent auth failure
    }
}

Types

type AuthorizationServerMetadata

type AuthorizationServerMetadata struct {
	// Issuer is the authorization server's issuer identifier URL
	Issuer string `json:"issuer"`

	// AuthorizationEndpoint is the URL of the authorization endpoint
	AuthorizationEndpoint string `json:"authorization_endpoint"`

	// TokenEndpoint is the URL of the token endpoint
	TokenEndpoint string `json:"token_endpoint"`

	// RegistrationEndpoint is the URL of the dynamic client registration endpoint (RFC 7591)
	RegistrationEndpoint string `json:"registration_endpoint,omitempty"`

	// ScopesSupported lists the OAuth scopes supported
	ScopesSupported []string `json:"scopes_supported,omitempty"`

	// ResponseTypesSupported lists the OAuth response types supported
	ResponseTypesSupported []string `json:"response_types_supported"`

	// GrantTypesSupported lists the OAuth grant types supported
	GrantTypesSupported []string `json:"grant_types_supported,omitempty"`

	// TokenEndpointAuthMethodsSupported lists the client authentication methods supported at the token endpoint
	TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"`

	// CodeChallengeMethodsSupported lists the PKCE code challenge methods supported
	CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"`

	// RevocationEndpoint is the URL of the OAuth 2.0 token revocation endpoint (RFC 7009)
	RevocationEndpoint string `json:"revocation_endpoint,omitempty"`

	// IntrospectionEndpoint is the URL of the OAuth 2.0 token introspection endpoint (RFC 7662)
	IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`

	// ClientIDMetadataDocumentSupported indicates support for Client ID Metadata Documents (MCP 2025-11-25)
	ClientIDMetadataDocumentSupported bool `json:"client_id_metadata_document_supported,omitempty"`

	// AuthorizationResponseIssParameterSupported indicates that this authorization
	// server includes the `iss` parameter in authorization responses (RFC 9207),
	// allowing clients talking to multiple authorization servers to detect mix-up
	// attacks.
	AuthorizationResponseIssParameterSupported bool `json:"authorization_response_iss_parameter_supported,omitempty"`

	// ClaimsSupported lists the claim names this server may emit in id_tokens
	// (OpenID Connect Discovery 1.0 §3).
	ClaimsSupported []string `json:"claims_supported,omitempty"`

	// SubjectTypesSupported lists the OIDC subject-identifier types this server
	// supports (`public` only — pairwise sub is not implemented).
	SubjectTypesSupported []string `json:"subject_types_supported,omitempty"`

	// IDTokenSigningAlgValuesSupported lists JWS `alg` values the server may use
	// to sign id_tokens. Required by OIDC Discovery 1.0 §3 even when the server
	// does not issue id_tokens itself.
	IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported,omitempty"`
}

AuthorizationServerMetadata represents OAuth 2.0 Authorization Server Metadata (RFC 8414)

type CallbackResult added in v0.2.46

type CallbackResult struct {
	// Code is the authorization code from a successful authorization.
	// Empty if the callback contains an error.
	Code string

	// State is the state parameter for CSRF validation.
	// Should match the state sent in the authorization request.
	State string

	// Error is the OAuth error code if authorization failed.
	// Common values: "access_denied", "login_required", "consent_required"
	Error string

	// ErrorDescription provides additional information about the error.
	// Human-readable text describing the error.
	ErrorDescription string

	// ErrorURI points to a web page with error documentation.
	ErrorURI string
}

CallbackResult represents the result of an OAuth authorization callback. It parses and holds the query parameters from the OAuth redirect.

The callback may contain either:

  • Success: Code and State parameters
  • Error: Error, ErrorDescription, and optionally ErrorURI parameters

Use Err() to get a typed error for error responses, including SilentAuthError for silent authentication failures.

func ParseCallbackQuery added in v0.2.46

func ParseCallbackQuery(code, state, errorCode, errorDescription, errorURI string) *CallbackResult

ParseCallbackQuery creates a CallbackResult from URL query parameters. This is a convenience function for parsing OAuth callback query strings.

Parameters:

  • code: The authorization code (from "code" query param)
  • state: The state parameter (from "state" query param)
  • errorCode: The error code (from "error" query param)
  • errorDescription: The error description (from "error_description" query param)
  • errorURI: The error URI (from "error_uri" query param)

func (*CallbackResult) Err added in v0.2.46

func (r *CallbackResult) Err() error

Err returns an appropriate error for the callback result. For silent auth failures (login_required, consent_required, interaction_required, account_selection_required), returns a *SilentAuthError that can be detected with IsSilentAuthError(). Returns nil if no error occurred.

Example usage:

q := r.URL.Query()
result := ParseCallbackQuery(q.Get("code"), q.Get("state"), q.Get("error"), q.Get("error_description"), q.Get("error_uri"))
if err := result.Err(); err != nil {
    if IsSilentAuthError(err) {
        // Fall back to interactive login
        return startInteractiveLogin(w, r)
    }
    return handleError(w, err)
}
// Process result.Code

func (*CallbackResult) IsError added in v0.2.46

func (r *CallbackResult) IsError() bool

IsError returns true if the callback contains an error. Use Err() to get the actual error with proper typing.

type ClientRegistrationRequest

type ClientRegistrationRequest struct {
	// RedirectURIs is the array of redirection URIs for use in redirect-based flows
	RedirectURIs []string `json:"redirect_uris,omitempty"`

	// TokenEndpointAuthMethod is the requested authentication method for the token endpoint
	TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`

	// GrantTypes is the array of OAuth 2.0 grant types the client will use
	GrantTypes []string `json:"grant_types,omitempty"`

	// ResponseTypes is the array of OAuth 2.0 response types the client will use
	ResponseTypes []string `json:"response_types,omitempty"`

	// ClientName is the human-readable name of the client
	ClientName string `json:"client_name,omitempty"`

	// ClientURI is the URL of the client's home page
	ClientURI string `json:"client_uri,omitempty"`

	// Scope is the space-separated list of scope values
	Scope string `json:"scope,omitempty"`

	// ClientType indicates if this is a "public" or "confidential" client
	// Public clients (mobile, SPA) can use "none" auth method
	// Confidential clients (server-side) must use client_secret_basic or client_secret_post
	ClientType string `json:"client_type,omitempty"`
}

ClientRegistrationRequest represents a dynamic client registration request

type ClientRegistrationResponse

type ClientRegistrationResponse struct {
	// ClientID is the unique client identifier
	ClientID string `json:"client_id"`

	// ClientSecret is the client secret (for confidential clients)
	ClientSecret string `json:"client_secret,omitempty"`

	// ClientIDIssuedAt is the time the client_id was issued
	ClientIDIssuedAt int64 `json:"client_id_issued_at,omitempty"`

	// ClientSecretExpiresAt is when the client_secret expires (0 = never)
	ClientSecretExpiresAt int64 `json:"client_secret_expires_at,omitempty"`

	// RedirectURIs is the array of redirection URIs
	RedirectURIs []string `json:"redirect_uris,omitempty"`

	// TokenEndpointAuthMethod is the authentication method for the token endpoint
	TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`

	// GrantTypes is the array of OAuth 2.0 grant types
	GrantTypes []string `json:"grant_types,omitempty"`

	// ResponseTypes is the array of OAuth 2.0 response types
	ResponseTypes []string `json:"response_types,omitempty"`

	// ClientName is the human-readable name of the client
	ClientName string `json:"client_name,omitempty"`

	// Scope is the space-separated list of scope values
	Scope string `json:"scope,omitempty"`

	// ClientType indicates if this is a "public" or "confidential" client
	ClientType string `json:"client_type,omitempty"`
}

ClientRegistrationResponse represents a dynamic client registration response

type Error added in v0.2.24

type Error struct {
	Code        string // OAuth error code (e.g., "invalid_request", "invalid_grant")
	Description string // Human-readable error description
	Status      int    // HTTP status code
}

Error represents an OAuth 2.0 error response. This type implements the standard error interface and provides structured information about OAuth protocol errors.

func NewError added in v0.2.24

func NewError(code, description string, status int) *Error

NewError creates a new OAuth error with the specified code, description, and HTTP status.

func (*Error) Error added in v0.2.24

func (e *Error) Error() string

Error implements the error interface

type ErrorResponse

type ErrorResponse struct {
	// Error is the error code
	Error string `json:"error"`

	// ErrorDescription provides additional information
	ErrorDescription string `json:"error_description,omitempty"`

	// ErrorURI points to error documentation
	ErrorURI string `json:"error_uri,omitempty"`
}

ErrorResponse represents an OAuth error response

type ForwardedIDTokenAcceptance added in v0.2.102

type ForwardedIDTokenAcceptance = server.ForwardedIDTokenAcceptance

ForwardedIDTokenAcceptance is the verified result of accepting a JWT forwarded from a trusted upstream identity provider.

type OAuthError deprecated

type OAuthError = Error

OAuthError is an alias for Error, provided for backward compatibility.

Deprecated: Use Error instead. This alias will be removed in a future major version.

type ProtectedResourceMetadata

type ProtectedResourceMetadata struct {
	// Resource is the identifier for the protected resource
	Resource string `json:"resource"`

	// AuthorizationServers lists the authorization servers that can issue tokens for this resource
	AuthorizationServers []string `json:"authorization_servers"`

	// BearerMethodsSupported lists the ways Bearer tokens can be sent (RFC 6750)
	BearerMethodsSupported []string `json:"bearer_methods_supported,omitempty"`

	// ResourceSigningAlgValuesSupported lists supported signing algorithms
	ResourceSigningAlgValuesSupported []string `json:"resource_signing_alg_values_supported,omitempty"`

	// ScopesSupported lists the scopes understood by this resource
	ScopesSupported []string `json:"scopes_supported,omitempty"`
}

ProtectedResourceMetadata represents OAuth 2.0 Protected Resource Metadata (RFC 9728)

type Server

type Server = server.Server

Server is the OAuth 2.1 authorization server. See server.Server.

func NewServer

func NewServer(
	provider providers.Provider,
	tokenStore storage.TokenStore,
	clientStore storage.ClientStore,
	flowStore storage.FlowStore,
	config *ServerConfig,
	logger *slog.Logger,
	opts ...ServerOption,
) (*Server, error)

NewServer creates a new OAuth server. See server.New.

func NewServerWithCombined added in v0.2.108

func NewServerWithCombined(
	provider providers.Provider,
	store storage.Combined,
	config *ServerConfig,
	logger *slog.Logger,
	opts ...ServerOption,
) (*Server, error)

NewServerWithCombined is a convenience wrapper for server.NewWithCombined — the additive constructor that takes a storage.Combined backend instead of three separate store arguments. Use it when your backend (memory, valkey, or anything else) implements all three storage interfaces.

type ServerConfig

type ServerConfig = server.Config

ServerConfig is the OAuth server configuration. See server.Config.

type ServerOption added in v0.2.121

type ServerOption = server.Option

ServerOption configures a Server during construction. See server.Option.

func WithAuditor added in v0.2.121

func WithAuditor(aud *security.Auditor) ServerOption

WithAuditor configures the security auditor. See server.WithAuditor.

func WithClientRegistrationRateLimiter added in v0.2.121

func WithClientRegistrationRateLimiter(rl *security.ClientRegistrationRateLimiter) ServerOption

WithClientRegistrationRateLimiter configures the registration rate limiter. See server.WithClientRegistrationRateLimiter.

func WithInstrumentation added in v0.2.121

func WithInstrumentation(inst *instrumentation.Instrumentation) ServerOption

WithInstrumentation installs an OpenTelemetry pipeline on the server. Build it with instrumentation.New and pass it here. See server.WithInstrumentation.

func WithMetadataFetchRateLimiter added in v0.2.121

func WithMetadataFetchRateLimiter(rl *security.RateLimiter) ServerOption

WithMetadataFetchRateLimiter configures the per-domain rate limiter for client-metadata-document fetches. See server.WithMetadataFetchRateLimiter.

func WithRateLimiter added in v0.2.121

func WithRateLimiter(rl *security.RateLimiter) ServerOption

WithRateLimiter configures the IP-based rate limiter. See server.WithRateLimiter.

func WithSecurityEventRateLimiter added in v0.2.121

func WithSecurityEventRateLimiter(rl *security.RateLimiter) ServerOption

WithSecurityEventRateLimiter configures the rate limiter that bounds security-event log emission. See server.WithSecurityEventRateLimiter.

func WithSessionCreationHandler added in v0.2.121

func WithSessionCreationHandler(h server.SessionCreationHandler) ServerOption

WithSessionCreationHandler registers a callback that fires when a new token family is created. See server.WithSessionCreationHandler.

func WithSessionRevocationHandler added in v0.2.121

func WithSessionRevocationHandler(h server.SessionRevocationHandler) ServerOption

WithSessionRevocationHandler registers a callback that fires when a token family is revoked. See server.WithSessionRevocationHandler.

func WithTokenRefreshHandler added in v0.2.121

func WithTokenRefreshHandler(h server.TokenRefreshHandler) ServerOption

WithTokenRefreshHandler registers a callback that fires after a provider token is refreshed. See server.WithTokenRefreshHandler.

func WithUserRateLimiter added in v0.2.121

func WithUserRateLimiter(rl *security.RateLimiter) ServerOption

WithUserRateLimiter configures the user-based rate limiter for authenticated requests. See server.WithUserRateLimiter.

type SilentAuthError added in v0.2.46

type SilentAuthError struct {
	// Code is the OAuth/OIDC error code.
	// Common values: "login_required", "consent_required", "interaction_required"
	Code string

	// Description is the optional error description from the IdP
	Description string
}

SilentAuthError represents an error from a silent authentication attempt. These errors indicate the IdP requires user interaction and the client should fall back to interactive login.

Silent authentication fails when:

  • No active session at the IdP (login_required)
  • User hasn't granted required scopes (consent_required)
  • IdP needs user interaction for other reasons (interaction_required)
  • Multiple accounts and none selected (account_selection_required)

See: https://openid.net/specs/openid-connect-core-1_0.html#AuthError

func (*SilentAuthError) Error added in v0.2.46

func (e *SilentAuthError) Error() string

Error implements the error interface.

type TokenResponse

type TokenResponse struct {
	// AccessToken is the access token
	AccessToken string `json:"access_token"`

	// TokenType is the type of token (always "Bearer")
	TokenType string `json:"token_type"`

	// ExpiresIn is the lifetime in seconds of the access token
	ExpiresIn int64 `json:"expires_in,omitempty"`

	// RefreshToken is the refresh token (optional)
	RefreshToken string `json:"refresh_token,omitempty"`

	// Scope is the scope of the access token
	Scope string `json:"scope,omitempty"`

	// IDToken is the OIDC ID token from the upstream provider (optional).
	// Per OpenID Connect Core 1.0 Section 3.1.3.3, this is REQUIRED for OIDC flows.
	// This enables clients to use id_token_hint and login_hint for silent re-authentication.
	IDToken string `json:"id_token,omitempty"`
}

TokenResponse represents an OAuth 2.0 token response

Directories

Path Synopsis
examples
basic command
Package main demonstrates basic OAuth 2.1 setup for MCP servers.
Package main demonstrates basic OAuth 2.1 setup for MCP servers.
cimd command
Package main demonstrates Client ID Metadata Document (CIMD) verification.
Package main demonstrates Client ID Metadata Document (CIMD) verification.
custom-scopes command
Package main demonstrates OAuth setup with multiple Google API scopes.
Package main demonstrates OAuth setup with multiple Google API scopes.
dex command
Package main demonstrates OAuth setup with the Dex OIDC provider.
Package main demonstrates OAuth setup with the Dex OIDC provider.
github command
Package main demonstrates OAuth setup with the GitHub OAuth provider.
Package main demonstrates OAuth setup with the GitHub OAuth provider.
jwt command
Package main demonstrates the AccessTokenFormatJWT mode of mcp-oauth.
Package main demonstrates the AccessTokenFormatJWT mode of mcp-oauth.
mcp-2025-11-25 command
Package main demonstrates MCP 2025-11-25 OAuth specification features.
Package main demonstrates MCP 2025-11-25 OAuth specification features.
production command
Package main demonstrates production-ready OAuth 2.1 setup for MCP servers.
Package main demonstrates production-ready OAuth 2.1 setup for MCP servers.
prometheus command
Package main demonstrates OAuth setup with Prometheus metrics.
Package main demonstrates OAuth setup with Prometheus metrics.
Package instrumentation provides OpenTelemetry (OTEL) instrumentation for the mcp-oauth library.
Package instrumentation provides OpenTelemetry (OTEL) instrumentation for the mcp-oauth library.
internal
constants
Package constants defines values shared between the root package and server/ to break the circular import that would arise from server importing the root (which already imports server for its type aliases).
Package constants defines values shared between the root package and server/ to break the circular import that would arise from server importing the root (which already imports server for its type aliases).
helpers
Package helpers provides common utility functions used across the mcp-oauth library.
Package helpers provides common utility functions used across the mcp-oauth library.
testutil
Package testutil provides testing utilities, mock implementations, and test fixtures for the mcp-oauth library.
Package testutil provides testing utilities, mock implementations, and test fixtures for the mcp-oauth library.
Package oauthconfig loads mcp-oauth configuration from environment variables.
Package oauthconfig loads mcp-oauth configuration from environment variables.
internal/valkeytls
Package valkeytls builds a *tls.Config for Valkey connections from a small set of feature-flag-shaped options.
Package valkeytls builds a *tls.Config for Valkey connections from a small set of feature-flag-shaped options.
Package providers defines the OAuth provider interface and types for user information.
Package providers defines the OAuth provider interface and types for user information.
dex
Package dex implements the OAuth provider interface for Dex (https://dexidp.io/).
Package dex implements the OAuth provider interface for Dex (https://dexidp.io/).
github
Package github implements the OAuth provider interface for GitHub OAuth Apps.
Package github implements the OAuth provider interface for GitHub OAuth Apps.
google
Package google provides a Google OAuth 2.0 provider implementation.
Package google provides a Google OAuth 2.0 provider implementation.
mock
Package mock provides mock implementations of the Provider interface for testing purposes.
Package mock provides mock implementations of the Provider interface for testing purposes.
oidc
Package oidc provides shared OpenID Connect client utilities for OAuth providers.
Package oidc provides shared OpenID Connect client utilities for OAuth providers.
tokencache
Package tokencache provides a generic LRU-bounded token cache for short-lived access tokens.
Package tokencache provides a generic LRU-bounded token cache for short-lived access tokens.
Package security provides security features for OAuth including encryption, rate limiting, audit logging, and secure header management.
Package security provides security features for OAuth including encryption, rate limiting, audit logging, and secure header management.
Package server provides OAuth 2.1 authorization server implementation with MCP support
Package server provides OAuth 2.1 authorization server implementation with MCP support
Package storage provides interfaces and utilities for OAuth token, client, and flow persistence.
Package storage provides interfaces and utilities for OAuth token, client, and flow persistence.
memory
Package memory provides an in-memory implementation of the OAuth storage interfaces.
Package memory provides an in-memory implementation of the OAuth storage interfaces.
mock
Package mock provides mock implementations of storage interfaces for testing purposes.
Package mock provides mock implementations of storage interfaces for testing purposes.
valkey
Package valkey provides a Valkey storage backend for the mcp-oauth library.
Package valkey provides a Valkey storage backend for the mcp-oauth library.

Jump to

Keyboard shortcuts

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