Feature: 007-oauth-e2e-testing Date: 2025-12-02
This feature adds comprehensive OAuth end-to-end testing infrastructure to mcpproxy, enabling developers to:
- Run OAuth tests locally without external dependencies
- Test all OAuth flows (auth code, device code, DCR, client credentials)
- Verify observability (logs, CLI output, doctor checks)
- Run browser-based tests with Playwright
- Go 1.24.0+
- Node.js 18+ (for Playwright tests)
- mcpproxy built:
go build -o mcpproxy ./cmd/mcpproxy
# Full OAuth E2E suite (Go + Playwright)
./scripts/run-oauth-e2e.sh
# Go integration tests only
go test ./tests/oauthserver/... -v
# Playwright browser tests only
cd e2e/playwright && npx playwright test# Auth code + PKCE flow
go test ./tests/oauthserver -run TestAuthCodePKCE -v
# Device code flow
go test ./tests/oauthserver -run TestDeviceCode -v
# Dynamic client registration
go test ./tests/oauthserver -run TestDCR -v
# Error handling
go test ./tests/oauthserver -run TestErrorHandling -v
# JWKS rotation
go test ./tests/oauthserver -run TestJWKSRotation -vpackage mytest
import (
"testing"
"github.com/your-org/mcpproxy-go/tests/oauthserver"
)
func TestMyOAuthFeature(t *testing.T) {
// Start server with defaults
server := oauthserver.Start(t, oauthserver.Options{})
defer server.Shutdown()
// Use server.IssuerURL, server.ClientID, etc.
t.Logf("OAuth server running at %s", server.IssuerURL)
// Configure mcpproxy or make HTTP requests
}func TestWithCustomOptions(t *testing.T) {
server := oauthserver.Start(t, oauthserver.Options{
// Disable features not needed
EnableDeviceCode: false,
EnableDCR: false,
// Fast token expiry for refresh testing
AccessTokenExpiry: 5 * time.Second,
// Custom scopes
SupportedScopes: []string{"read", "write", "admin", "custom"},
// Test credentials
ValidUsers: map[string]string{
"alice": "password123",
"bob": "secret456",
},
})
defer server.Shutdown()
}func TestErrorHandling(t *testing.T) {
server := oauthserver.Start(t, oauthserver.Options{
ErrorMode: oauthserver.ErrorMode{
TokenInvalidClient: true, // Force invalid_client errors
},
})
defer server.Shutdown()
// Test that mcpproxy handles the error correctly
}| Endpoint | Description |
|---|---|
/.well-known/oauth-authorization-server |
OAuth metadata (RFC 8414) |
/.well-known/openid-configuration |
OIDC discovery (alias) |
/jwks.json |
Public keys for JWT verification |
/authorize |
Authorization endpoint with login UI |
/token |
Token endpoint (all grant types) |
/registration |
Dynamic client registration |
/device_authorization |
Device code initiation |
/device_verification |
Device code approval UI |
/protected |
Returns 401 for detection testing |
server := oauthserver.Start(t, oauthserver.Options{
DetectionMode: oauthserver.Discovery,
})
// mcpproxy will fetch /.well-known/oauth-authorization-serverserver := oauthserver.Start(t, oauthserver.Options{
DetectionMode: oauthserver.WWWAuthenticate,
})
// Hit /protected to get 401 with WWW-Authenticate
resp, _ := http.Get(server.ProtectedResourceURL)
// Parse WWW-Authenticate header for authorization_uri# After OAuth flow completes
./mcpproxy auth status --server=test-server
# Expected output includes:
# - Authorization endpoint URL
# - Token endpoint URL
# - Scopes
# - Token expiry
# - PKCE status# Should print authorization URL before opening browser
./mcpproxy auth login --server=test-server
# Look for:
# "Opening browser to: http://127.0.0.1:XXXXX/authorize?..."
# with resource, scopes, and PKCE parameters visible# With misconfigured OAuth
./mcpproxy doctor
# Expected output:
# - OAuth configuration issues
# - Discovery endpoint reachability
# - Actionable hintscd e2e/playwright
# Install browsers (first time)
npx playwright install chromium
# Run all OAuth tests
npx playwright test oauth-login.spec.ts
# Run with UI (debugging)
npx playwright test --ui
# Run headed (see browser)
npx playwright test --headed- Happy Path Login: Fill credentials, approve consent, verify redirect
- Invalid Password: Submit wrong password, verify error page
- Denied Consent: Uncheck consent, verify error=access_denied
- Timeout: Close browser mid-flow, verify cleanup
OAuth E2E tests run automatically on:
- Push to
mainornextbranches - PRs labeled with
test-oauth
To trigger manually:
# Add label to PR
gh pr edit --add-label test-oauth# Check for port conflicts
lsof -i :8080
# Use verbose logging
go test ./tests/oauthserver -v -run TestBasic# Reinstall browsers
npx playwright install --force
# Run with debug logging
DEBUG=pw:api npx playwright test# Check JWKS is accessible
curl http://127.0.0.1:XXXXX/jwks.json | jq
# Verify token claims
# Decode JWT at jwt.io| File | Purpose |
|---|---|
tests/oauthserver/server.go |
Main test server |
tests/oauthserver/options.go |
Configuration |
tests/oauthserver/jwt.go |
JWT generation |
tests/oauthserver/server_test.go |
Server unit tests |
scripts/run-oauth-e2e.sh |
E2E orchestration |
e2e/playwright/oauth-login.spec.ts |
Browser tests |
After running tests successfully:
- Add new test cases as needed for specific scenarios
- Update
CLAUDE.mdif adding new test commands - Update
MANUAL_TESTING.mdwith OAuth test procedures