authserver

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Feb 2, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package authserver provides configuration and validation for the OAuth authorization server.

Package authserver provides a centralized OAuth 2.0 Authorization Server implementation using ory/fosite for issuing JWTs to clients.

The auth server supports:

  • OAuth 2.0 Authorization Code flow with PKCE (RFC 7636)
  • Dynamic Client Registration (RFC 7591)
  • Upstream IDP delegation (authenticates users via external IdP like Google, Okta)
  • JWT access tokens with configurable lifespans
  • OIDC discovery (/.well-known/openid-configuration)
  • OAuth 2.0 Authorization Server Metadata (/.well-known/oauth-authorization-server, RFC 8414)

Usage

The primary entry point is authserver.New(), which creates an OAuth authorization server with a single handler. Storage is a required parameter:

stor := storage.NewMemoryStorage()
server, err := authserver.New(ctx, cfg, stor)
if err != nil {
    return err
}
// Mount handler on your HTTP server (serves all OAuth/OIDC endpoints)
mux.Handle("/", server.Handler())

Configuration

The server requires a Config struct with issuer URL, signing key configuration, upstream IDP settings, and allowed audiences. See the Config type for details.

cfg := authserver.Config{
    Issuer:           "https://auth.example.com",
    Upstreams:        []authserver.UpstreamConfig{{Config: upstreamCfg}},
    AllowedAudiences: []string{"https://mcp.example.com"},
}
stor := storage.NewMemoryStorage()
server, err := authserver.New(ctx, cfg, stor)

Storage

The auth server requires a storage backend for tokens, authorization codes, and client registrations. Currently available:

  • In-memory storage (suitable for single-instance deployments)

Example with memory storage:

stor := storage.NewMemoryStorage()
server, err := authserver.New(ctx, cfg, stor)

IDP Token Storage

When using upstream IDP delegation, tokens from the external IdP are stored and can be retrieved via the IDPTokenStorage interface for use by middleware (e.g., token swap middleware that replaces JWT auth with upstream tokens).

Subpackages

The authserver package is organized into subpackages:

  • server: HTTP handlers and OAuth server configuration
  • storage: Token and authorization storage backends
  • upstream: Upstream Identity Provider communication

Index

Constants

View Source
const CurrentSchemaVersion = "v0.1.0"

CurrentSchemaVersion is the current version of the authserver RunConfig schema.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Issuer is the issuer identifier for this authorization server.
	// This will be included in the "iss" claim of issued tokens.
	Issuer string

	// KeyProvider provides signing keys for JWT operations.
	// Supports key rotation by returning multiple public keys for JWKS.
	// If nil, an ephemeral key will be auto-generated (development only).
	//
	// Production: Use keys.NewFileProvider() or keys.NewProviderFromConfig()
	// Testing: Use a mock or keys.NewGeneratingProvider()
	KeyProvider keys.KeyProvider

	// HMACSecrets contains the symmetric secrets used for signing authorization codes
	// and refresh tokens (opaque tokens). Unlike the asymmetric SigningKey which
	// signs JWTs for distributed verification, these secrets are used internally
	// by the authorization server only.
	// Current secret must be at least 32 bytes and cryptographically random.
	// Must be consistent across all replicas in multi-instance deployments.
	// Supports secret rotation via the Rotated field.
	HMACSecrets *servercrypto.HMACSecrets

	// AccessTokenLifespan is the duration that access tokens are valid.
	// If zero, defaults to 1 hour.
	AccessTokenLifespan time.Duration

	// RefreshTokenLifespan is the duration that refresh tokens are valid.
	// If zero, defaults to 7 days.
	RefreshTokenLifespan time.Duration

	// AuthCodeLifespan is the duration that authorization codes are valid.
	// If zero, defaults to 10 minutes.
	AuthCodeLifespan time.Duration

	// Upstreams contains configurations for connecting to upstream IDPs.
	// At least one upstream is required - the server delegates authentication to the upstream IDP.
	// Currently only a single upstream is supported.
	Upstreams []UpstreamConfig

	// ScopesSupported lists the OAuth 2.0 scope values advertised in discovery documents.
	// If nil or empty, defaults to ["openid", "offline_access"].
	// This is advertised in /.well-known/openid-configuration and
	// /.well-known/oauth-authorization-server discovery endpoints.
	ScopesSupported []string

	// AllowedAudiences is the list of valid resource URIs that tokens can be issued for.
	// Per RFC 8707, the "resource" parameter in authorization and token requests is
	// validated against this list. MCP clients are required to include the resource
	// parameter, so this should be configured with the canonical URIs of all MCP servers
	// this authorization server issues tokens for.
	//
	// Security: An empty list means NO audiences are permitted (secure default).
	// When empty, any request with a "resource" parameter will be rejected with
	// "invalid_target". Configure this for proper MCP specification compliance.
	AllowedAudiences []string
}

Config is the pure configuration for the OAuth authorization server. All values must be fully resolved (no file paths, no env vars). This is the interface that consumers should use to configure the server.

func (*Config) GetUpstream

func (c *Config) GetUpstream() *upstream.OAuth2Config

GetUpstream returns the primary upstream configuration. For current single-upstream deployments, this returns the only configured upstream. Returns nil if no upstreams are configured (call Validate first).

func (*Config) Validate

func (c *Config) Validate() error

Validate checks that the Config is valid.

type OAuth2UpstreamRunConfig added in v0.9.0

type OAuth2UpstreamRunConfig struct {
	// AuthorizationEndpoint is the URL for the OAuth authorization endpoint.
	AuthorizationEndpoint string `json:"authorization_endpoint" yaml:"authorization_endpoint"`

	// TokenEndpoint is the URL for the OAuth token endpoint.
	TokenEndpoint string `json:"token_endpoint" yaml:"token_endpoint"`

	// ClientID is the OAuth 2.0 client identifier registered with the upstream IDP.
	ClientID string `json:"client_id" yaml:"client_id"`

	// ClientSecretFile is the path to a file containing the OAuth 2.0 client secret.
	// Mutually exclusive with ClientSecretEnvVar. Optional for public clients using PKCE.
	ClientSecretFile string `json:"client_secret_file,omitempty" yaml:"client_secret_file,omitempty"`

	// ClientSecretEnvVar is the name of an environment variable containing the client secret.
	// Mutually exclusive with ClientSecretFile. Optional for public clients using PKCE.
	ClientSecretEnvVar string `json:"client_secret_env_var,omitempty" yaml:"client_secret_env_var,omitempty"`

	// RedirectURI is the callback URL where the upstream IDP will redirect after authentication.
	// When not specified, defaults to `{issuer}/oauth/callback`.
	RedirectURI string `json:"redirect_uri,omitempty" yaml:"redirect_uri,omitempty"`

	// Scopes are the OAuth scopes to request from the upstream IDP.
	Scopes []string `json:"scopes,omitempty" yaml:"scopes,omitempty"`

	// UserInfo contains configuration for fetching user information (required for OAuth2).
	UserInfo *UserInfoRunConfig `json:"userinfo" yaml:"userinfo"`
}

OAuth2UpstreamRunConfig contains configuration for pure OAuth 2.0 providers. OAuth 2.0 providers require explicit endpoint configuration.

type OIDCUpstreamRunConfig added in v0.9.0

type OIDCUpstreamRunConfig struct {
	// IssuerURL is the OIDC issuer URL for automatic endpoint discovery.
	// Must be a valid HTTPS URL.
	IssuerURL string `json:"issuer_url" yaml:"issuer_url"`

	// ClientID is the OAuth 2.0 client identifier registered with the upstream IDP.
	ClientID string `json:"client_id" yaml:"client_id"`

	// ClientSecretFile is the path to a file containing the OAuth 2.0 client secret.
	// Mutually exclusive with ClientSecretEnvVar. Optional for public clients using PKCE.
	ClientSecretFile string `json:"client_secret_file,omitempty" yaml:"client_secret_file,omitempty"`

	// ClientSecretEnvVar is the name of an environment variable containing the client secret.
	// Mutually exclusive with ClientSecretFile. Optional for public clients using PKCE.
	ClientSecretEnvVar string `json:"client_secret_env_var,omitempty" yaml:"client_secret_env_var,omitempty"`

	// RedirectURI is the callback URL where the upstream IDP will redirect after authentication.
	// When not specified, defaults to `{issuer}/oauth/callback`.
	RedirectURI string `json:"redirect_uri,omitempty" yaml:"redirect_uri,omitempty"`

	// Scopes are the OAuth scopes to request from the upstream IDP.
	// If not specified, defaults to ["openid", "offline_access"].
	Scopes []string `json:"scopes,omitempty" yaml:"scopes,omitempty"`

	// UserInfoOverride allows customizing UserInfo fetching behavior for OIDC providers.
	// By default, the UserInfo endpoint is discovered automatically via OIDC discovery.
	UserInfoOverride *UserInfoRunConfig `json:"userinfo_override,omitempty" yaml:"userinfo_override,omitempty"`
}

OIDCUpstreamRunConfig contains OIDC provider configuration. OIDC providers support automatic endpoint discovery via the issuer URL.

type RunConfig added in v0.9.0

type RunConfig struct {
	// SchemaVersion is the version of the RunConfig schema.
	SchemaVersion string `json:"schema_version" yaml:"schema_version"`

	// Issuer is the issuer identifier for this authorization server.
	// This will be included in the "iss" claim of issued tokens.
	// Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
	Issuer string `json:"issuer" yaml:"issuer"`

	// SigningKeyConfig configures the signing key provider for JWT operations.
	// If nil or empty, an ephemeral signing key will be auto-generated (development only).
	SigningKeyConfig *SigningKeyRunConfig `json:"signing_key_config,omitempty" yaml:"signing_key_config,omitempty"`

	// HMACSecretFiles contains file paths to HMAC secrets for signing authorization codes
	// and refresh tokens (opaque tokens).
	// First file is the current secret (must be at least 32 bytes), subsequent files
	// are for rotation/verification of existing tokens.
	// If empty, an ephemeral secret will be auto-generated (development only).
	HMACSecretFiles []string `json:"hmac_secret_files,omitempty" yaml:"hmac_secret_files,omitempty"`

	// TokenLifespans configures the duration that various tokens are valid.
	// If nil, defaults are applied (access: 1h, refresh: 7d, authCode: 10m).
	TokenLifespans *TokenLifespanRunConfig `json:"token_lifespans,omitempty" yaml:"token_lifespans,omitempty"`

	// Upstreams configures connections to upstream Identity Providers.
	// At least one upstream is required - the server delegates authentication to these providers.
	// Currently only a single upstream is supported.
	Upstreams []UpstreamRunConfig `json:"upstreams" yaml:"upstreams"`

	// ScopesSupported lists the OAuth 2.0 scope values advertised in discovery documents.
	// If empty, defaults to ["openid", "offline_access"].
	ScopesSupported []string `json:"scopes_supported,omitempty" yaml:"scopes_supported,omitempty"`

	// AllowedAudiences is the list of valid resource URIs that tokens can be issued for.
	// Per RFC 8707, the "resource" parameter in authorization and token requests is
	// validated against this list. Required for MCP compliance.
	AllowedAudiences []string `json:"allowed_audiences" yaml:"allowed_audiences"`
}

RunConfig is the serializable configuration for the embedded auth server. It contains no secrets - only file paths and environment variable names that will be resolved at runtime.

This follows the same pattern as pkg/runner.RunConfig - it's serializable, versioned, and portable. Secrets are referenced by file path or environment variable name, never embedded directly.

type Server added in v0.9.0

type Server interface {
	// Handler returns an http.Handler that serves all OAuth/OIDC endpoints:
	//   - /.well-known/openid-configuration (OIDC Discovery)
	//   - /.well-known/oauth-authorization-server (RFC 8414 OAuth AS Metadata)
	//   - /.well-known/jwks.json (JSON Web Key Set)
	//   - /oauth/authorize (Authorization endpoint)
	//   - /oauth/token (Token endpoint)
	//   - /oauth/callback (Upstream IDP callback)
	//   - /oauth/register (Dynamic Client Registration, RFC 7591)
	//
	// The handler uses internal routing - the consumer doesn't need to know
	// about the endpoint structure.
	Handler() http.Handler

	// IDPTokenStorage returns storage for upstream IDP tokens.
	// Returns nil if no upstream IDP is configured.
	IDPTokenStorage() storage.UpstreamTokenStorage

	// Close releases resources held by the server.
	Close() error
}

Server is the OAuth authorization server. It provides HTTP handlers that serve all OAuth/OIDC endpoints.

func New added in v0.9.0

func New(ctx context.Context, cfg Config, stor storage.Storage) (Server, error)

New creates a new OAuth authorization server. The storage parameter is required and determines where OAuth state is persisted. Use storage.NewMemoryStorage() for single-instance deployments or provide a distributed storage backend for production deployments.

type SigningKeyRunConfig added in v0.9.0

type SigningKeyRunConfig struct {
	// KeyDir is the directory containing PEM-encoded private key files.
	// All key filenames are relative to this directory.
	// In Kubernetes, this is typically a mounted Secret volume.
	KeyDir string `json:"key_dir,omitempty" yaml:"key_dir,omitempty"`

	// SigningKeyFile is the filename of the primary signing key (relative to KeyDir).
	// This key is used for signing new tokens.
	SigningKeyFile string `json:"signing_key_file,omitempty" yaml:"signing_key_file,omitempty"`

	// FallbackKeyFiles are filenames of additional keys for verification (relative to KeyDir).
	// These keys are included in the JWKS endpoint for token verification but are NOT
	// used for signing new tokens. Useful for key rotation.
	FallbackKeyFiles []string `json:"fallback_key_files,omitempty" yaml:"fallback_key_files,omitempty"`
}

SigningKeyRunConfig configures where to load signing keys from. Keys are loaded from PEM-encoded files on disk (typically mounted from secrets).

type TokenLifespanRunConfig added in v0.9.0

type TokenLifespanRunConfig struct {
	// AccessTokenLifespan is the duration that access tokens are valid.
	// If empty, defaults to 1 hour.
	AccessTokenLifespan string `json:"access_token_lifespan,omitempty" yaml:"access_token_lifespan,omitempty"`

	// RefreshTokenLifespan is the duration that refresh tokens are valid.
	// If empty, defaults to 7 days (168h).
	RefreshTokenLifespan string `json:"refresh_token_lifespan,omitempty" yaml:"refresh_token_lifespan,omitempty"`

	// AuthCodeLifespan is the duration that authorization codes are valid.
	// If empty, defaults to 10 minutes.
	AuthCodeLifespan string `json:"auth_code_lifespan,omitempty" yaml:"auth_code_lifespan,omitempty"`
}

TokenLifespanRunConfig holds token lifetime configuration. All durations are specified as Go duration strings (e.g., "1h", "30m", "168h").

type UpstreamConfig

type UpstreamConfig struct {
	// Name uniquely identifies this upstream.
	// Used for routing decisions and session binding in multi-upstream scenarios.
	// If empty when only one upstream is configured, defaults to "default".
	Name string `json:"name,omitempty" yaml:"name,omitempty"`

	// Config contains the OAuth 2.0 provider configuration.
	Config *upstream.OAuth2Config `json:"config" yaml:"config"`
}

UpstreamConfig wraps an upstream IDP configuration with identifying metadata.

type UpstreamProviderType added in v0.9.0

type UpstreamProviderType string

UpstreamProviderType identifies the type of upstream Identity Provider.

const (
	// UpstreamProviderTypeOIDC is for OIDC providers with discovery support.
	UpstreamProviderTypeOIDC UpstreamProviderType = "oidc"

	// UpstreamProviderTypeOAuth2 is for pure OAuth 2.0 providers with explicit endpoints.
	UpstreamProviderTypeOAuth2 UpstreamProviderType = "oauth2"
)

type UpstreamRunConfig added in v0.9.0

type UpstreamRunConfig struct {
	// Name uniquely identifies this upstream.
	// Used for routing decisions and session binding in multi-upstream scenarios.
	// If empty when only one upstream is configured, defaults to "default".
	Name string `json:"name,omitempty" yaml:"name,omitempty"`

	// Type specifies the provider type: "oidc" or "oauth2".
	Type UpstreamProviderType `json:"type" yaml:"type"`

	// OIDCConfig contains OIDC-specific configuration.
	// Required when Type is "oidc", must be nil when Type is "oauth2".
	OIDCConfig *OIDCUpstreamRunConfig `json:"oidc_config,omitempty" yaml:"oidc_config,omitempty"`

	// OAuth2Config contains OAuth 2.0-specific configuration.
	// Required when Type is "oauth2", must be nil when Type is "oidc".
	OAuth2Config *OAuth2UpstreamRunConfig `json:"oauth2_config,omitempty" yaml:"oauth2_config,omitempty"`
}

UpstreamRunConfig configures an upstream identity provider.

type UserInfoFieldMappingRunConfig added in v0.9.0

type UserInfoFieldMappingRunConfig struct {
	// SubjectFields is an ordered list of field names to try for the user ID.
	// The first non-empty value found will be used.
	// Default: ["sub"]
	SubjectFields []string `json:"subject_fields,omitempty" yaml:"subject_fields,omitempty"`

	// NameFields is an ordered list of field names to try for the display name.
	// The first non-empty value found will be used.
	// Default: ["name"]
	NameFields []string `json:"name_fields,omitempty" yaml:"name_fields,omitempty"`

	// EmailFields is an ordered list of field names to try for the email address.
	// The first non-empty value found will be used.
	// Default: ["email"]
	EmailFields []string `json:"email_fields,omitempty" yaml:"email_fields,omitempty"`
}

UserInfoFieldMappingRunConfig maps provider-specific field names to standard UserInfo fields. This allows adapting non-standard provider responses to the canonical UserInfo structure.

type UserInfoRunConfig added in v0.9.0

type UserInfoRunConfig struct {
	// EndpointURL is the URL of the userinfo endpoint.
	EndpointURL string `json:"endpoint_url" yaml:"endpoint_url"`

	// HTTPMethod is the HTTP method to use for the userinfo request.
	// If not specified, defaults to GET.
	HTTPMethod string `json:"http_method,omitempty" yaml:"http_method,omitempty"`

	// AdditionalHeaders contains extra headers to include in the userinfo request.
	// Useful for providers that require specific headers (e.g., GitHub's Accept header).
	AdditionalHeaders map[string]string `json:"additional_headers,omitempty" yaml:"additional_headers,omitempty"`

	// FieldMapping contains custom field mapping configuration for non-standard providers.
	// If nil, standard OIDC field names are used ("sub", "name", "email").
	FieldMapping *UserInfoFieldMappingRunConfig `json:"field_mapping,omitempty" yaml:"field_mapping,omitempty"`
}

UserInfoRunConfig contains UserInfo endpoint configuration. This supports both standard OIDC UserInfo endpoints and custom provider-specific endpoints.

Directories

Path Synopsis
Package server provides the OAuth 2.0 authorization server implementation for ToolHive.
Package server provides the OAuth 2.0 authorization server implementation for ToolHive.
crypto
Package crypto provides cryptographic utilities for the OAuth authorization server.
Package crypto provides cryptographic utilities for the OAuth authorization server.
handlers
Package handlers provides HTTP handlers for the OAuth 2.0 authorization server endpoints.
Package handlers provides HTTP handlers for the OAuth 2.0 authorization server endpoints.
keys
Package keys provides signing key management for the OAuth authorization server.
Package keys provides signing key management for the OAuth authorization server.
keys/mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
registration
Package registration provides OAuth client types and utilities, including RFC 8252 compliant loopback redirect URI support for native OAuth clients.
Package registration provides OAuth client types and utilities, including RFC 8252 compliant loopback redirect URI support for native OAuth clients.
session
Package session provides OAuth session management for the authorization server.
Package session provides OAuth session management for the authorization server.
Package storage provides storage interfaces and implementations for the OAuth authorization server.
Package storage provides storage interfaces and implementations for the OAuth authorization server.
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
Package upstream provides types and implementations for upstream Identity Provider communication in the OAuth authorization server.
Package upstream provides types and implementations for upstream Identity Provider communication in the OAuth authorization server.
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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