Configuration Guide

Complete reference for oauth-mcp-proxy configuration options.


Config Struct

type Config struct {
    // Required
    Provider string // "hmac", "okta", "google", "azure"
    Audience string // Your API audience

    // Provider-specific
    Issuer    string // OIDC issuer URL (Okta/Google/Azure)
    JWTSecret []byte // Secret key (HMAC only)

    // Optional - OAuth Mode
    Mode string // "native" or "proxy" - auto-detected

    // Optional - Proxy Mode
    ClientID     string // OAuth client ID
    ClientSecret string // OAuth client secret
    ServerURL    string // Your server's public URL
    RedirectURIs string // Allowed redirect URIs

    // Optional - Logging
    Logger Logger // Custom logger implementation
}

Configuration Methods

Direct Config

Create Config struct directly:

cfg := &oauth.Config{
    Provider:  "okta",
    Issuer:    "https://company.okta.com",
    Audience:  "api://my-server",
    ServerURL: "https://my-server.com",
}
_, oauthOption, _ := oauth.WithOAuth(mux, cfg)

ConfigBuilder (v0.2.0+)

Use fluent API with auto-generated ServerURL:

cfg, _ := oauth.NewConfigBuilder().
    WithProvider("okta").
    WithIssuer("https://company.okta.com").
    WithAudience("api://my-server").
    WithHost("my-server.com").
    WithPort("443").
    WithTLS(true).  // Auto-generates https://my-server.com:443
    Build()

Benefits:

  • Auto-generates ServerURL from host/port/TLS

  • Validates config during Build()

  • Cleaner, more readable code

FromEnv() (v0.2.0+)

Read configuration from environment variables:

cfg, _ := oauth.FromEnv()
_, oauthOption, _ := oauth.WithOAuth(mux, cfg)

Environment variables:

  • OAUTH_PROVIDER - Provider name

  • OAUTH_MODE - OAuth mode (optional)

  • OIDC_ISSUER - Issuer URL

  • OIDC_AUDIENCE - Audience

  • OIDC_CLIENT_ID - Client ID (proxy mode)

  • OIDC_CLIENT_SECRET - Client secret (proxy mode)

  • OAUTH_REDIRECT_URIS - Redirect URIs (proxy mode)

  • JWT_SECRET - HMAC secret

  • MCP_URL - Full server URL (or auto-generated from below)

  • MCP_HOST - Server host (default: localhost)

  • MCP_PORT - Server port (default: 8080)

  • HTTPS_CERT_FILE - TLS cert file (enables HTTPS)

  • HTTPS_KEY_FILE - TLS key file (enables HTTPS)

Benefits:

  • 12-factor app compliant

  • Easy Kubernetes/Docker deployment

  • No code changes for config updates


Required Fields

Provider

Type: string Required: Yes Values: "hmac", "okta", "google", "azure"

Specifies which OAuth provider to use for token validation.

Provider: "okta"  // Use Okta OIDC validation

See: Provider Guides for setup instructions

Audience

Type: string Required: Yes Purpose: Validates the aud claim in JWT tokens

The audience must match exactly. This prevents token reuse across services.

Examples:

// Custom audience
Audience: "api://my-mcp-server"

// Google (use Client ID)
Audience: "123456789.apps.googleusercontent.com"

// Azure (use Application ID or App ID URI)
Audience: "api://my-server"
// or
Audience: "12345678-1234-1234-1234-123456789012"

Provider-Specific Fields

Issuer

Type: string Required: For OIDC providers (okta, google, azure) Not used: HMAC provider

The OAuth provider's issuer URL. Must match token's iss claim exactly.

Examples:

// Okta
Issuer: "https://yourcompany.okta.com"

// Google
Issuer: "https://accounts.google.com"

// Azure AD (single tenant)
Issuer: "https://login.microsoftonline.com/{tenant-id}/v2.0"

// Azure AD (multi-tenant)
Issuer: "https://login.microsoftonline.com/common/v2.0"

Important:

  • No trailing slash

  • Must serve /.well-known/openid-configuration

  • HTTPS required

JWTSecret

Type: []byte Required: For HMAC provider only Not used: OIDC providers

Shared secret for HMAC-SHA256 token validation.

Examples:

// From environment (recommended)
JWTSecret: []byte(os.Getenv("JWT_SECRET"))

// Minimum 32 bytes recommended
JWTSecret: []byte("your-very-long-secret-key-min-32-bytes")

// Generate securely
secret := make([]byte, 32)
rand.Read(secret)
JWTSecret: secret

Security: Never hardcode! Use environment variables. See SECURITY.md.


OAuth Mode

Mode

Type: string Optional: Auto-detected if not specified Values: "native", "proxy"

Determines whether client or server handles OAuth flow.

Auto-detection:

// If ClientID is provided → proxy mode
// If ClientID is empty → native mode
Mode: ""  // Let library auto-detect

Explicit:

Mode: "native"  // Client does OAuth
Mode: "proxy"   // Server proxies OAuth

Native Mode

When: OAuth-capable clients (Claude Desktop, browser apps)

Client: Authenticates directly with provider → Gets token → Calls MCP server Server: Only validates tokens (no OAuth endpoints used)

Config:

oauth.WithOAuth(mux, &oauth.Config{
    Mode:     "native",  // Or omit (auto-detected)
    Provider: "okta",
    Issuer:   "https://company.okta.com",
    Audience: "api://my-server",
    // No ClientID/ServerURL/RedirectURIs needed
})

OAuth endpoints: Return 404 with helpful message (not needed by client)

Proxy Mode

When: Simple clients that can't do OAuth (CLI tools, legacy clients)

Client: Calls MCP server → Server proxies to provider → Returns token to client Server: Full OAuth authorization server functionality

Config:

oauth.WithOAuth(mux, &oauth.Config{
    Mode:         "proxy",  // Or omit (auto-detected from ClientID)
    Provider:     "okta",
    Issuer:       "https://company.okta.com",
    Audience:     "api://my-server",
    ClientID:     "your-client-id",           // Required for proxy mode
    ClientSecret: "your-client-secret",       // Required for proxy mode
    ServerURL:    "https://your-server.com",  // Required for proxy mode
    RedirectURIs: "https://your-server.com/oauth/callback",  // Required
})

OAuth endpoints: Fully functional (/oauth/authorize, /oauth/callback, /oauth/token)

Mode Comparison:

Native
Proxy

Client capability

Can do OAuth

Cannot do OAuth

OAuth flow

Client ↔ Provider

Client ↔ Server ↔ Provider

Config required

Minimal

Full (ClientID, ServerURL, etc.)

Endpoints active

Metadata only

All endpoints

Use case

Production apps

Simple clients


Proxy Mode Fields

ClientID

Type: string Required: For proxy mode Purpose: OAuth client identifier from provider

Obtained from your OAuth provider:

  • Okta: Application → General → Client ID

  • Google: Cloud Console → Credentials → OAuth 2.0 Client ID

  • Azure: App registrations → Application (client) ID

ClientID: "0oa..."  // Okta
ClientID: "123.apps.googleusercontent.com"  // Google
ClientID: "12345678-1234-1234-1234-123456789012"  // Azure

ClientSecret

Type: string Required: For proxy mode (confidential clients) Purpose: OAuth client secret for token exchange

Security:

// ✅ From environment
ClientSecret: os.Getenv("OAUTH_CLIENT_SECRET")

// ❌ Never hardcode
ClientSecret: "abc123..."  // SECURITY VIOLATION

See: SECURITY.md for secret management best practices.

ServerURL

Type: string Required: For proxy mode Purpose: Your MCP server's public URL

Used for:

  • OAuth metadata endpoints (issuer URL)

  • Redirect URI construction

  • Endpoint URL generation

ServerURL: "https://mcp-server.example.com"      // Production
ServerURL: "https://mcp-server.herokuapp.com"     // Cloud deployment
ServerURL: "http://localhost:8080"                // Local testing

Requirements:

  • HTTPS in production

  • No trailing slash

  • Publicly accessible (for OAuth provider callbacks)

RedirectURIs

Type: string Required: For proxy mode Purpose: OAuth redirect URI validation

Single URI (Fixed Redirect):

RedirectURIs: "https://your-server.com/oauth/callback"

Server uses this URI with provider. For security, client redirects must be localhost only.

Multiple URIs (Allowlist):

RedirectURIs: "https://app1.com/callback,https://app2.com/callback,https://app3.com/callback"

Comma-separated list. Client's redirect_uri must exactly match one of these.

Security:

  • HTTPS required for non-localhost

  • No wildcards allowed

  • Exact string match

  • See SECURITY.md for redirect URI security


Optional Fields

Logger

Type: Logger interface Default: Uses log.Printf with level prefixes Purpose: Custom logging integration

Implement Logger interface to integrate with your logging system:

type Logger interface {
    Debug(msg string, args ...interface{})
    Info(msg string, args ...interface{})
    Warn(msg string, args ...interface{})
    Error(msg string, args ...interface{})
}

Examples:

Zap:

type ZapLogger struct{ logger *zap.Logger }

func (l *ZapLogger) Info(msg string, args ...interface{}) {
    l.logger.Sugar().Infof(msg, args...)
}
// ... implement Debug, Warn, Error

cfg := &oauth.Config{
    Provider: "okta",
    Logger:   &ZapLogger{logger: zapLogger},
}

Logrus:

type LogrusLogger struct{ logger *logrus.Logger }

func (l *LogrusLogger) Info(msg string, args ...interface{}) {
    l.logger.Infof(msg, args...)
}
// ... implement Debug, Warn, Error

cfg := &oauth.Config{
    Logger: &LogrusLogger{logger: logrusLogger},
}

Default behavior:

[INFO] OAuth2: Authorization request - client_id: ...
[WARN] SECURITY: Invalid redirect URI ...
[ERROR] OAuth2: Token validation failed: ...

What gets logged: See examples/README.md


Validation

Configuration is validated when calling WithOAuth() or NewServer():

_, oauthOption, err := oauth.WithOAuth(mux, cfg)
if err != nil {
    // err describes what's wrong:
    // - "provider is required"
    // - "JWTSecret is required for HMAC provider"
    // - "proxy mode requires ClientID"
    // - etc.
    log.Fatal(err)
}

Validation Rules

All modes:

  • Provider must be one of: hmac, okta, google, azure

  • Audience is required

  • Provider-specific fields validated (JWTSecret for HMAC, Issuer for OIDC)

Proxy mode:

  • ClientID required

  • ServerURL required

  • RedirectURIs required

Native mode:

  • ClientID, ServerURL, RedirectURIs optional (ignored if provided)


Complete Examples

HMAC (Testing)

oauth.WithOAuth(mux, &oauth.Config{
    Provider:  "hmac",
    Audience:  "api://my-server",
    JWTSecret: []byte(os.Getenv("JWT_SECRET")),
})
oauth.WithOAuth(mux, &oauth.Config{
    Provider: "okta",
    Issuer:   os.Getenv("OKTA_ISSUER"),
    Audience: "api://my-server",
})

Okta (Proxy - For Simple Clients)

oauth.WithOAuth(mux, &oauth.Config{
    Provider:     "okta",
    Issuer:       os.Getenv("OKTA_ISSUER"),
    Audience:     "api://my-server",
    ClientID:     os.Getenv("OKTA_CLIENT_ID"),
    ClientSecret: os.Getenv("OKTA_CLIENT_SECRET"),
    ServerURL:    "https://mcp.example.com",
    RedirectURIs: "https://mcp.example.com/oauth/callback",
})

Google

oauth.WithOAuth(mux, &oauth.Config{
    Provider: "google",
    Issuer:   "https://accounts.google.com",
    Audience: os.Getenv("GOOGLE_CLIENT_ID"),  // Use Client ID as audience
})

Azure AD

oauth.WithOAuth(mux, &oauth.Config{
    Provider: "azure",
    Issuer:   fmt.Sprintf("https://login.microsoftonline.com/%s/v2.0",
                          os.Getenv("AZURE_TENANT_ID")),
    Audience: os.Getenv("AZURE_CLIENT_ID"),
})

Environment Variables Pattern

Recommended .env structure:

# OAuth Provider
OAUTH_PROVIDER=okta
OAUTH_ISSUER=https://yourcompany.okta.com
OAUTH_AUDIENCE=api://my-mcp-server

# HMAC (if using)
JWT_SECRET=your-32-byte-secret-key

# Proxy Mode (if using)
OAUTH_CLIENT_ID=your-client-id
OAUTH_CLIENT_SECRET=your-client-secret
OAUTH_SERVER_URL=https://your-server.com
OAUTH_REDIRECT_URIS=https://your-server.com/oauth/callback

Load in code:

import "github.com/joho/godotenv"

func main() {
    godotenv.Load()

    oauth.WithOAuth(mux, &oauth.Config{
        Provider:     os.Getenv("OAUTH_PROVIDER"),
        Issuer:       os.Getenv("OAUTH_ISSUER"),
        Audience:     os.Getenv("OAUTH_AUDIENCE"),
        ClientID:     os.Getenv("OAUTH_CLIENT_ID"),
        ClientSecret: os.Getenv("OAUTH_CLIENT_SECRET"),
        ServerURL:    os.Getenv("OAUTH_SERVER_URL"),
        RedirectURIs: os.Getenv("OAUTH_REDIRECT_URIS"),
        JWTSecret:    []byte(os.Getenv("JWT_SECRET")),
    })
}

See Also

Last updated

Was this helpful?