OAuth 2.1 Authentication for Kafka MCP Server
Overview
Kafka MCP Server supports OAuth 2.1 authentication when running in HTTP transport mode. This enables secure, token-based authentication for MCP clients accessing the server over HTTP.
The implementation uses [email protected], a standalone OAuth 2.1 library designed specifically for Go MCP servers.
Features
Two OAuth Modes: Native mode (client-managed) and Proxy mode (server-managed)
Multiple Providers: Support for HMAC, Okta, Google, and Azure AD
Token Caching: 5-minute token validation cache for performance
Bearer Token Authentication: Standard Authorization header support
Automatic Endpoint Registration: OAuth routes automatically configured
Graceful Shutdown: Proper HTTP server lifecycle management
Architecture
OAuth Flow
┌─────────────────┐
│ MCP Client │
│ (Cursor, etc) │
└────────┬────────┘
│
│ Bearer Token
│ Authorization: Bearer <token>
▼
┌─────────────────────────────────┐
│ HTTP Server │
│ │
│ ┌──────────────────────────┐ │
│ │ OAuth Middleware │ │
│ │ - Token Extraction │ │
│ │ - Token Validation │ │
│ │ - User Context Inject │ │
│ └──────────┬───────────────┘ │
│ ▼ │
│ ┌──────────────────────────┐ │
│ │ MCP Server Handler │ │
│ │ /mcp endpoint │ │
│ └──────────────────────────┘ │
└─────────────────────────────────┘
│
▼
┌─────────────────┐
│ Kafka Cluster │
└─────────────────┘Implementation Architecture
The OAuth integration follows a specific initialization sequence:
Mux Creation:
http.NewServeMux()created inmain()OAuth Registration:
CreateOAuthOption(cfg, mux)registers OAuth routes on muxServer Creation:
NewMCPServer(name, version, oauthOption)with OAuth middlewareHTTP Server:
startHTTPServer()mounts MCP handler and starts server
This ensures OAuth routes and middleware are properly configured before the server starts handling requests.
OAuth Modes
Native Mode (Client-Managed)
Best for: Environments where clients can handle OAuth flows directly.
Characteristics:
Zero server-side secrets
Clients obtain tokens from OAuth provider
Server validates Bearer tokens only
Most secure option
Configuration:
export MCP_TRANSPORT=http
export MCP_HTTP_PORT=8080
export OAUTH_ENABLED=true
export OAUTH_MODE=native
export OAUTH_PROVIDER=okta
export OAUTH_SERVER_URL=http://localhost:8080
export OIDC_ISSUER=https://company.okta.com
export OIDC_AUDIENCE=api://kafka-mcp-serverProxy Mode (Server-Managed)
Best for: Centralized OAuth management, simple clients.
Characteristics:
Server manages OAuth flow
Requires client ID, client secret, JWT secret
Server handles token exchange
Useful for centralized control
Configuration:
export MCP_TRANSPORT=http
export MCP_HTTP_PORT=8080
export OAUTH_ENABLED=true
export OAUTH_MODE=proxy
export OAUTH_PROVIDER=google
export OAUTH_SERVER_URL=http://localhost:8080
export OIDC_ISSUER=https://accounts.google.com
export OIDC_CLIENT_ID=your-client-id.apps.googleusercontent.com
export OIDC_CLIENT_SECRET=your-client-secret
export OIDC_AUDIENCE=your-client-id.apps.googleusercontent.com
export OAUTH_REDIRECT_URIS=http://localhost:8080/oauth/callback
export JWT_SECRET=$(openssl rand -hex 32)Supported Providers
1. HMAC (Development/Testing)
Simple symmetric key authentication for local development.
export OAUTH_PROVIDER=hmac
export OAUTH_MODE=native
export JWT_SECRET=$(openssl rand -hex 32)
export OIDC_ISSUER=http://localhost:8080
export OIDC_AUDIENCE=api://kafka-mcp-serverUse case: Local testing without external OAuth provider.
2. Okta
Enterprise SSO provider.
Setup Requirements:
Okta account and tenant
OAuth application configured in Okta
API audience defined
Native Mode:
export OAUTH_PROVIDER=okta
export OAUTH_MODE=native
export OIDC_ISSUER=https://company.okta.com
export OIDC_AUDIENCE=api://kafka-mcp-serverProxy Mode: Add client credentials
export OIDC_CLIENT_ID=your-okta-client-id
export OIDC_CLIENT_SECRET=your-okta-client-secret
export OAUTH_REDIRECT_URIS=http://localhost:8080/oauth/callback
export JWT_SECRET=$(openssl rand -hex 32)3. Google
Google Workspace authentication.
Setup Requirements:
Google Cloud project
OAuth 2.0 credentials configured
Authorized redirect URIs
Configuration:
export OAUTH_PROVIDER=google
export OIDC_ISSUER=https://accounts.google.com
export OIDC_AUDIENCE=your-client-id.apps.googleusercontent.com4. Azure AD (azure)
Microsoft identity platform.
Setup Requirements:
Azure AD tenant
App registration in Azure portal
API permissions configured
Configuration:
export OAUTH_PROVIDER=azure
export OIDC_ISSUER=https://login.microsoftonline.com/{tenant-id}/v2.0
export OIDC_AUDIENCE=api://your-app-idEnvironment Variables
HTTP Server Configuration
MCP_TRANSPORT
Transport mode
stdio
Yes (set to http)
MCP_HTTP_PORT
HTTP server port
8080
No
OAuth Configuration
OAUTH_ENABLED
Enable OAuth
false
Yes
OAUTH_MODE
Mode: native or proxy
native
No
OAUTH_PROVIDER
Provider: hmac, okta, google, azuread
okta
No
OAUTH_SERVER_URL
Full server URL
-
Yes
OIDC Configuration
OIDC_ISSUER
OAuth issuer URL
Yes
OIDC_AUDIENCE
OAuth audience
Yes
OIDC_CLIENT_ID
OAuth client ID
Proxy mode only
OIDC_CLIENT_SECRET
OAuth client secret
Proxy mode only
Proxy Mode Only
OAUTH_REDIRECT_URIS
Comma-separated redirect URIs
Yes
JWT_SECRET
JWT signing secret
Yes
OAuth Endpoints
When OAuth is enabled, the following endpoints are automatically registered:
Discovery Endpoints
/.well-known/oauth-authorization-server- OAuth 2.1 metadata (RFC 8414)/.well-known/openid-configuration- OIDC discovery/.well-known/oauth-protected-resource- Protected resource metadata/.well-known/jwks.json- JSON Web Key Set
Proxy Mode Endpoints
/oauth/authorize- Authorization endpoint/oauth/callback- OAuth callback endpoint/oauth/token- Token exchange endpoint/oauth/register- Dynamic client registration
MCP Endpoint
/mcp- MCP server endpoint (protected when OAuth enabled)
Testing OAuth
Local Testing with HMAC Provider
The HMAC provider is perfect for local development without external dependencies:
# Start server with HMAC OAuth
export MCP_TRANSPORT=http
export MCP_HTTP_PORT=8080
export OAUTH_ENABLED=true
export OAUTH_PROVIDER=hmac
export OAUTH_MODE=native
export OAUTH_SERVER_URL=http://localhost:8080
export OIDC_ISSUER=http://localhost:8080
export OIDC_AUDIENCE=api://kafka-mcp-server
export JWT_SECRET=$(openssl rand -hex 32)
export KAFKA_BROKERS=localhost:9092
./bin/kafka-mcp-serverCheck OAuth metadata:
curl http://localhost:8080/.well-known/oauth-authorization-server | jqExpected output:
{
"issuer": "http://localhost:8080",
"authorization_endpoint": "http://localhost:8080/oauth/authorize",
"token_endpoint": "http://localhost:8080/oauth/token",
"jwks_uri": "http://localhost:8080/.well-known/jwks.json",
...
}Testing with Token
# Generate test token (implementation-specific)
TOKEN="your-bearer-token"
# Access MCP endpoint with token
curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/mcpSecurity Considerations
Production Requirements
TLS/HTTPS Required: Always use TLS in production
Handle TLS at proxy/load balancer level
Set
OAUTH_SERVER_URLto HTTPS URL
Secrets Management: Never commit secrets to version control
Use secret management systems (Vault, AWS Secrets Manager)
Rotate JWT secrets regularly
Store client secrets securely
Token Security:
Library caches validated tokens for 5 minutes
Tokens must be sent in Authorization header
Invalid/expired tokens are rejected automatically
Logging: OAuth tokens and secrets are never logged
Environment-Specific Recommendations
Development:
Use HMAC provider for simplicity
OAUTH_SERVER_URL=http://localhost:8080is acceptableGenerate strong JWT secrets:
openssl rand -hex 32
Staging:
Use real OAuth provider (Okta, Google, Azure AD)
Configure TLS termination
Test with actual tokens
Validate issuer and audience matching
Production:
TLS/HTTPS mandatory
Strong, rotated JWT secrets
Monitor token validation errors
Set up alerts for authentication failures
Use native mode when possible (no server-side secrets)
Troubleshooting
Server Fails to Start
Issue: failed to setup OAuth
Solutions:
Verify all required environment variables are set
Check OIDC_ISSUER is a valid URL
For proxy mode, ensure CLIENT_ID, CLIENT_SECRET, and JWT_SECRET are set
Review server logs for specific error messages
OAuth Endpoints Return 404
Issue: OAuth discovery endpoints not found
Solutions:
Verify
OAUTH_ENABLED=trueConfirm
MCP_TRANSPORT=httpCheck server logs for "OAuth configured" message
Ensure server started successfully
Token Validation Fails
Issue: Valid tokens are rejected
Solutions:
Verify token is sent in Authorization header:
Authorization: Bearer <token>Check issuer in token claims matches
OIDC_ISSUERVerify audience in token claims matches
OIDC_AUDIENCEEnsure OAuth provider is accessible from server
Check token has not expired
Review server logs for validation error details
Graceful Shutdown Issues
Issue: Server doesn't shutdown cleanly
Solutions:
Ensure server receives SIGINT/SIGTERM signal
Check for context cancellation in logs
Default shutdown timeout is 5 seconds
Review server logs for shutdown errors
Code Examples
Accessing User Context in Tools
When OAuth is enabled, authenticated user information is available in tool handlers:
import (
oauth "github.com/tuannvm/oauth-mcp-proxy"
)
func myToolHandler(ctx context.Context, request ToolRequest) (*ToolResponse, error) {
// Extract authenticated user from context
user, ok := oauth.GetUserFromContext(ctx)
if !ok {
return nil, fmt.Errorf("authentication required")
}
slog.Info("Tool accessed by authenticated user",
"username", user.Username,
"email", user.Email,
"subject", user.Subject)
// Proceed with tool logic
// ...
}Custom OAuth Configuration
For advanced use cases, you can customize OAuth behavior by modifying internal/mcp/server.go:
// Example: Add custom logger
oauthConfig.Logger = customLogger
// Example: Customize provider-specific settings
if cfg.OAuthProvider == "okta" {
// Provider-specific configuration
}Migration Guide
From STDIO to HTTP with OAuth
Step 1: Ensure backwards compatibility
# Existing STDIO configuration still works
export MCP_TRANSPORT=stdio
export KAFKA_BROKERS=localhost:9092Step 2: Add HTTP transport without OAuth
export MCP_TRANSPORT=http
export MCP_HTTP_PORT=8080
export KAFKA_BROKERS=localhost:9092Step 3: Enable OAuth
export MCP_TRANSPORT=http
export MCP_HTTP_PORT=8080
export OAUTH_ENABLED=true
export OAUTH_MODE=native
export OAUTH_PROVIDER=okta
export OAUTH_SERVER_URL=https://your-domain.com
export OIDC_ISSUER=https://company.okta.com
export OIDC_AUDIENCE=api://kafka-mcp-server
export KAFKA_BROKERS=localhost:9092Step 4: Update MCP clients
Configure clients to send Bearer tokens
Update connection URL to HTTP endpoint
Test token validation
References
Support
For OAuth-related issues:
Check server logs for detailed error messages
Review oauth-mcp-proxy documentation
Consult provider-specific setup guides (Okta, Google, Azure AD)
Open an issue on GitHub with relevant logs (redact secrets!)
Last updated
Was this helpful?