OAuth 2.1 Implementation Guide
Overview
This document tracks the step-by-step implementation of OAuth 2.1 authentication for kafka-mcp-server using [email protected]. Follow this guide sequentially and update checkboxes as you complete each step.
CRITICAL ARCHITECTURAL NOTE: OAuth option MUST be passed to NewMCPServer() at creation time. This requires refactoring main.go to create the OAuth option before creating the MCP server instance.
Implementation Progress
Phase 1: Add Dependencies
Task
Add oauth-mcp-proxy library to the project.
Commands
Verification
Expected output: github.com/tuannvm/oauth-mcp-proxy v1.0.0
Phase 2: Update Configuration
File: internal/config/config.go
internal/config/config.goChanges Required
1. Add Import for strconv
Ensure strconv is imported:
2. Add New Fields to Config Struct
Add after existing fields:
3. Update LoadConfig Function
Add environment variable parsing (insert before the return statement):
Verification
Create a test file internal/config/config_test.go:
Run test:
Phase 3: Add OAuth Helper Function
File: internal/mcp/server.go
internal/mcp/server.goChanges Required
1. Add Imports
Update imports at the top of the file:
2. Add CreateOAuthOption Function
Add this function to internal/mcp/server.go:
Verification
Ensure the file compiles:
Expected: No errors
Phase 4: Refactor Main Entry Point
File: cmd/main.go
cmd/main.goChanges Required
CRITICAL: This is the most significant change. The MCP server must be created AFTER the OAuth option is prepared.
1. Add Imports
Ensure these imports are present:
2. Refactor main() Function
Replace the server creation section:
Verification
Build the binary:
Expected: Binary created without errors
Phase 5: Update Server Start Function
File: internal/mcp/server.go
internal/mcp/server.goChanges Required
Update Start Function Signature
Modify the Start function to accept the mux parameter:
Replace startHTTPServer Function
Replace the "HTTP transport not yet implemented" placeholder:
Verification
Test the server in different modes:
Test STDIO Mode (Backwards Compatibility)
Expected: Server starts in STDIO mode, no errors
Test HTTP Mode Without OAuth
Expected: Server starts on port 8080, /mcp endpoint accessible
Phase 6: Update Documentation
File: CLAUDE.md
CLAUDE.mdAdd OAuth section after the existing configuration sections (after TLS configuration):
Proxy Mode Example (Google)
Proxy mode: Server manages OAuth flow and token exchange.
OAuth Endpoints
When OAuth is enabled, these endpoints are automatically registered:
/.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/oauth/authorize- Authorization endpoint (proxy mode)/oauth/callback- Callback endpoint (proxy mode)/oauth/token- Token endpoint (proxy mode)/mcp- MCP server endpoint (protected when OAuth enabled)
Testing OAuth with HMAC Provider
For local testing without external OAuth provider:
Troubleshooting
Issue: "invalid OAuth configuration" or "failed to setup OAuth"
Verify all required fields for your mode are set (see examples above)
Check OIDC_ISSUER and OIDC_AUDIENCE are valid URLs
For proxy mode, ensure OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, and JWT_SECRET are set
Issue: "mux is required when OAuth is enabled"
This is an internal error; check that HTTP transport is properly configured
Issue: Token validation fails
Verify token is sent in Authorization header:
Authorization: Bearer <token>Check issuer and audience in token claims match configuration
Confirm OAuth provider is accessible from the server
Check server logs for detailed validation errors
Issue: Server starts but OAuth endpoints return 404
Verify OAuth is enabled:
OAUTH_ENABLED=trueCheck server logs for "OAuth configured" message
Ensure you're using HTTP transport, not STDIO
Security Notes
TLS Required: Always use TLS/HTTPS in production (handled at proxy/load balancer level)
Secrets Management: Never commit JWT_SECRET or OIDC_CLIENT_SECRET to version control
Token Caching: Library caches validated tokens for 5 minutes for performance
Rotation: Rotate JWT secrets regularly in proxy mode
Logging: OAuth tokens and secrets are never logged
Run tests:
Expected: All tests pass
Phase 8: Integration Tests
File: internal/mcp/server_test.go
internal/mcp/server_test.goCreate HTTP server integration tests:
Run tests:
Phase 9: Manual Testing
Test Checklist
9.1 STDIO Mode (Backwards Compatibility)
Expected: Server starts successfully in STDIO mode
9.2 HTTP Mode Without OAuth
Expected: MCP endpoint accessible, OAuth endpoints not available
9.3 HTTP Mode With Native OAuth (HMAC Provider)
Expected:
Server logs show "OAuth configured" with provider=hmac
OAuth metadata endpoints return valid JSON
MCP endpoint at
/mcpis available
9.4 HTTP Mode With Proxy OAuth (Google - Configuration Only)
Expected:
Server starts successfully
Logs show "OAuth configured" with provider=google, mode=proxy
Proxy endpoints return responses (not 404)
Phase 10: Security Review
Security Checklist
Configuration Security
Check:
Runtime Security
Deployment Security
Code Review
Progress Notes
2025-01-23 - Implementation Guide Created
Created comprehensive implementation guide
Documented critical architectural requirement: OAuth option must be passed at server creation
Provided detailed step-by-step instructions for all 10 phases
Included verification steps and test cases
2025-10-23 - OAuth Implementation Completed
Phases Completed:
✅ Phase 1: Added [email protected] dependency
✅ Phase 2: Extended Config struct with 11 OAuth fields (HTTP port, OAuth settings, OIDC config)
✅ Phase 3: Implemented CreateOAuthOption() helper function
✅ Phase 4: Refactored cmd/main.go to create OAuth option before MCPServer
✅ Phase 5: Implemented HTTP transport with StreamableHTTPServer and graceful shutdown
✅ Phase 6: Created comprehensive docs/oauth.md and updated README.md
✅ Phase 7: Wrote 21 unit tests (6 config tests + 15 MCP server tests)
Test Results:
All 21 tests passing (config + mcp packages)
Test coverage includes:
Config parsing for all OAuth fields (native/proxy modes)
CreateOAuthOption with various configurations
HTTP server startup with/without OAuth
Graceful shutdown verification
Port conflict handling
Multiple OAuth providers (HMAC, Okta, Google, Azure)
Invalid configuration handling
Edge cases (nil mux, unsupported transport, etc.)
Gemini 2.5 Pro Code Review:
No critical issues found
Architecture validated as correct
All edge cases handled properly
Graceful shutdown enhancement implemented
Key Implementation Details:
OAuth routes registered on mux before MCPServer creation
Token extraction via
oauth.CreateHTTPContextFunc()MCP endpoint exposed at
/mcpHTTP server uses context for 5-second graceful shutdown
Backwards compatible: STDIO mode unchanged
Issues Encountered
2025-10-23 - Unused Context Parameter
Issue: ctx parameter in startHTTPServer was unused
Solution: Implemented graceful shutdown using context with 5-second timeout
Impact: Better production readiness, clean server shutdown on SIGINT/SIGTERM
Time spent: 10 minutes
2025-10-23 - Missing oauth-mcp-proxy in go.mod
Issue: Initial build failed with "no required module provides package"
Solution: Ran
go get github.com/tuannvm/[email protected] && go mod tidyImpact: Dependencies properly resolved
Time spent: 2 minutes
Decisions Made
2025-10-23 - OAuth Option Architecture
Decision: Refactor main.go to create OAuth option before NewMCPServer
Rationale: Required by [email protected] API - option must be passed at server creation
Impact: Major refactor to main.go but cleaner separation of concerns
Alternative Considered: Try to add OAuth after server creation - would not work with library API
2025-10-23 - Graceful Shutdown Implementation
Decision: Use http.Server with context-based shutdown instead of http.ListenAndServe
Rationale: Gemini review identified unused ctx parameter; graceful shutdown best practice
Impact: Clean shutdown with 5-second timeout, proper resource cleanup
Code Change: Goroutine listens for ctx.Done() and calls httpServer.Shutdown()
2025-10-23 - Minimal OAuth Validation
Decision: No config validation in application code, rely on oauth-mcp-proxy library
Rationale: Keep implementation minimal, library handles validation
Impact: Cleaner code, validation errors surface at runtime with clear messages from library
Trade-off: Could add validation for better error messages, but adds complexity
2025-10-23 - Documentation Strategy
Decision: Create dedicated docs/oauth.md instead of putting everything in CLAUDE.md
Rationale: OAuth configuration is complex, deserves comprehensive standalone guide
Impact: Better user experience, easier to maintain, can reference from README
Content: Architecture diagrams, provider-specific guides, troubleshooting, security best practices
2025-10-23 - HMAC Provider JWTSecret Handling
Issue: HMAC provider requires JWTSecret in both native and proxy modes
Solution: Set JWTSecret for HMAC provider regardless of mode, then conditionally for proxy mode
Impact: HMAC provider works correctly in native mode for local testing
Code: Added separate check:
if cfg.OAuthProvider == "hmac" { oauthConfig.JWTSecret = []byte(cfg.JWTSecret) }
2025-10-23 - Provider Name Correction
Issue: Documentation used "azuread" but library expects "azure"
Solution: Updated all docs and config comments to use "azure"
Impact: Tests pass, provider name matches library expectations
Files: config.go, oauth.md, README.md
2025-10-23 - Security Review Completed
Configuration Security: ✅ No hardcoded secrets, no secret logging, all env vars documented
Runtime Security: ✅ Token validation via library, errors properly wrapped
Deployment Security: ✅ TLS documented as required, secrets rotation documented
Code Security: ✅ No credentials in code, proper error handling, input validation by library
Architecture Security: ✅ OAuth option timing correct, mux validation, graceful shutdown
Result: All security requirements met, no critical vulnerabilities found
Additional Checks: Verified HMAC provider works, provider validation, backwards compatibility maintained
Verification Commands
Quick verification after implementation:
Rollback Plan
If critical issues arise during implementation:
Quick Rollback (Development)
Selective Rollback
Revert go.mod changes:
Revert config changes:
Revert server changes:
Revert main.go:
Verify STDIO still works:
Success Criteria
Implementation is complete and successful when:
Functional Requirements
Code Quality
Documentation
Security
Testing
Implementation Status: ✅ COMPLETE
All phases completed successfully. Ready for production deployment.
Next Steps After Implementation
Create Pull Request
Ensure all tests pass
Update CHANGELOG.md
Request code review
Staging Deployment
Deploy to staging environment
Test with real OAuth provider (Okta or Google)
Verify token validation with actual tokens
Documentation
Add provider-specific setup guides (Okta, Google, Azure AD)
Create deployment runbook
Document monitoring and troubleshooting procedures
Production Preparation
Set up secrets management (e.g., Vault, AWS Secrets Manager)
Configure TLS termination at load balancer
Set up monitoring and alerting
Create rollback procedures
Support and Resources
oauth-mcp-proxy docs: https://pkg.go.dev/github.com/tuannvm/[email protected]
mcp-go docs: https://pkg.go.dev/github.com/mark3labs/[email protected]
OAuth 2.1 spec: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12
Project issues: https://github.com/tuannvm/kafka-mcp-server/issues
Last updated
Was this helpful?