Improve client.js and curl-examples.sh usability

Fix PKCE implementation, SSE parsing, error handling, and usage clarity.
Add --help flag and improve output messaging for both examples.
This commit is contained in:
Basil Hosmer 2025-10-07 14:36:41 -04:00
commit 7b7aa513f5
No known key found for this signature in database
3 changed files with 328 additions and 272 deletions

View file

@ -2,7 +2,7 @@
Complete listing of all endpoints provided by each server in the architecture.
## Auth Server (Port 3001)
## Auth Server
Standalone OAuth 2.0 authorization server that handles authentication and token management.
@ -37,7 +37,7 @@ Local simulation of upstream IDP (would be external in production):
---
## MCP Server (Port 3232)
## MCP Server
MCP resource server that implements the Model Context Protocol with delegated authentication.

View file

@ -6,9 +6,9 @@ This document describes different OAuth 2.0 architecture patterns for MCP server
Per the MCP specification, "the authorization server may be hosted with the resource server or as a separate entity." This leads to two primary patterns for implementing OAuth in MCP servers.
## Pattern 1: Separate Authorization Server (Implemented)
## Pattern 1: Separate Authorization Server (Recommended)
The current implementation uses this production-ready pattern with separate authorization and resource servers.
The current implementation demonstrates this pattern with separate authorization and resource servers. (Note: the authorization server is for demonstration purposes only.)
### Architecture
@ -19,7 +19,7 @@ The current implementation uses this production-ready pattern with separate auth
│ │ │ (port 3001) │validate │ (port 3232) │
│ │<────────│ │ │ │
│ │ token │ Issues tokens │ │ Serves MCP │
│ │ │ │ │ resources │
│ │ └──────────────────┘ │ resources │
│ │────────────────────────────────────> │ │
│ │ MCP requests with token │ │
└─────────────┘ └─────────────────┘
@ -27,11 +27,11 @@ The current implementation uses this production-ready pattern with separate auth
### Components
1. **Authorization Server** (port 3001)
1. **Demo Authorization Server** (port 3001)
- Handles OAuth 2.0 authorization flow
- Issues and manages tokens
- Provides token introspection endpoint (RFC 7662)
- Can be replaced with Auth0, Okta, Google OAuth, etc.
- Should be replaced with Auth0, Okta, Google OAuth, etc.
2. **MCP Resource Server** (port 3232)
- Serves MCP protocol resources
@ -39,113 +39,24 @@ The current implementation uses this production-ready pattern with separate auth
- Contains no OAuth authorization code
- Focuses purely on MCP functionality
### Benefits
### Using a Commercial Auth Provider
- **Standards Compliance**: Follows OAuth 2.0 best practices
- **Flexibility**: Easy to swap auth providers
- **Scalability**: Servers scale independently
- **Security**: Clear security boundaries
- **Maintainability**: Separation of concerns
Replacing the demo auth server with a commercial provider:
### Real-World Use Cases
- **SaaS Applications**: Using Auth0 or Okta for authentication
- **Enterprise**: Integrating with corporate SSO (SAML, LDAP)
- **Social Login**: Google, GitHub, Facebook authentication
- **Cloud Native**: AWS Cognito, Azure AD integration
### Implementation Details
The MCP server validates tokens by calling the auth server's `/introspect` endpoint:
```typescript
// In MCP server
const response = await fetch(`${AUTH_SERVER_URL}/introspect`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `token=${accessToken}`
});
const introspection = await response.json();
if (introspection.active) {
// Token is valid, extract user info
const userId = introspection.sub;
}
```
1. **Configure provider**: Set up OAuth app in commercial provider (e.g. Auth0/Okta)
2. **Update metadata URL**: Point to provider's discovery endpoint
3. **Configure introspection**: Set up token validation
4. **Update redirect URIs**: Configure allowed callbacks
5. **Migrate users**: Import existing users if needed
6. **Test integration**: Verify full OAuth flow
---
## Pattern 2: Embedded Authorization Server (Alternative)
## Pattern 2: Embedded Authorization Server (Alternative/Legacy)
An alternative pattern where the OAuth server is embedded within the MCP server. This demonstrates a self-hosted OAuth 2.1 authorization server running in the same process as the MCP server.
The MCP spec describes an alternative pattern where the OAuth server is embedded within the MCP server. However, this pattern is not recommended in the general case, and is not demonstrated in this codebase.
### Architecture
```
┌─────────────┐ ┌─────────────────────────┐
│ │ OAuth │ │
│ MCP Client │────────>│ MCP Server │
│ │ │ ┌──────────────────┐ │
│ │<────────│ │ OAuth Server │ │
│ │ token │ └──────────────────┘ │
│ │ │ ┌──────────────────┐ │
│ │────────>│ │ MCP Resources │ │
│ │ MCP │ └──────────────────┘ │
└─────────────┘ └─────────────────────────┘
```
### Upstream Delegation Pattern
Embedded OAuth often delegates user authentication to an upstream identity provider while maintaining control over token issuance:
```
MCP Client MCP+OAuth Server Upstream IDP
│ │ (Corporate SSO)
│──1. /authorize───────────────>│ │
│<───(show auth page)───────────│ │
│ │ │
│──2. Click "Continue"──────────>│ │
│<──redirect to upstream────────│ │
│ │ │
│──3. /upstream/authorize────────────────────────────────────────>│
│<──(authenticate user)──────────────────────────────────────────│
│──4. Provide credentials────────────────────────────────────────>│
│<──redirect with userId─────────────────────────────────────────│
│ │ │
│──5. /callback with userId───────>│ │
│ │──(validate userId) │
│ │──(issue MCP tokens) │
│<──redirect with auth code──────│ │
│ │ │
│──6. /token (exchange code)─────>│ │
│<──MCP access token─────────────│ │
```
### Characteristics
- **Single Server**: OAuth and MCP in one process
- **Port**: Typically runs on single port (e.g., 3232)
- **Token Validation**: In-process, direct database access
- **Deployment**: Simpler, fewer moving parts
- **Upstream Delegation**: Can delegate authentication to corporate SSO while controlling token issuance
### Benefits
- **Simplicity**: Single server to deploy and manage
- **Performance**: No network hop for token validation
- **Self-Contained**: All functionality in one codebase
- **Control**: Full control over token issuance while leveraging existing identity infrastructure
### Drawbacks
- **Coupling**: Auth and MCP logic intertwined
- **Scalability**: Can't scale auth independently
- **Flexibility**: Harder to switch auth providers
- **Updates**: Auth changes require MCP server updates
### Use Cases
### Possible Use Cases
- **Enterprise Deployments**: Organizations needing control over OAuth token issuance while leveraging existing corporate identity infrastructure (LDAP, Active Directory, SAML)
- **Proof of Concepts**: Quick prototypes and demonstrations
@ -153,39 +64,6 @@ MCP Client MCP+OAuth Server Upstream IDP
- **Isolated Systems**: Air-gapped environments without external connectivity
- **Custom Auth Requirements**: Specialized authentication needs not met by standard providers
### Typical Configuration
Environment variables for embedded pattern:
```bash
BASE_URI=http://localhost:3232 # Single server URL
PORT=3232 # Single port for OAuth + MCP
REDIS_URL=redis://localhost:6379 # Session storage
UPSTREAM_IDP_URL=https://corp.sso # Optional: upstream identity provider
```
### Code Organization
Typical structure for embedded OAuth implementation:
```
src/
├── index.ts # Main entry point (MCP + OAuth + routing)
├── auth/
│ ├── provider.ts # OAuth server implementation
│ └── auth-core.ts # Token generation, PKCE utilities
├── services/
│ ├── mcp.ts # MCP protocol implementation
│ ├── auth.ts # Auth service integration
│ ├── redis-auth.ts # Redis auth operations
│ └── redisTransport.ts # Redis-backed transport
├── handlers/
│ ├── oauth.ts # OAuth endpoints (/authorize, /token)
│ ├── mcp-shttp.ts # Streamable HTTP handler
│ ├── mcp-sse.ts # SSE handler
│ └── upstream-idp.ts # Upstream IDP integration
└── utils/
└── logger.ts # Structured logging
```
---
## Comparison
@ -195,42 +73,11 @@ src/
| **Architecture** | 2+ servers | 1 server |
| **OAuth endpoints** | On auth server | On MCP server |
| **Token validation** | Remote (introspection) | In-process |
| **Deployment** | More complex | Simpler |
| **Scalability** | Independent scaling | Coupled scaling |
| **Provider integration** | Easy (standard APIs) | Difficult |
| **Code organization** | Clear separation | Mixed concerns |
| **Network hops** | Additional for validation | None for validation |
| **Upstream IDP support** | Via auth server | Direct integration |
| **Production readiness** | ✅ Recommended | ⚠️ Limited use cases |
---
## Migration Path
### From Embedded to Separate
If starting with embedded OAuth, migration to separate servers involves:
1. **Extract auth code**: Move OAuth handlers to separate service
2. **Implement introspection**: Add RFC 7662 endpoint
3. **Update MCP server**: Replace in-process validation with introspection calls
4. **Update configuration**: Point MCP server to auth server URL
5. **Migrate upstream IDP**: Move delegation logic to auth server
6. **Test thoroughly**: Ensure token flow works correctly
### From Separate to Commercial Provider
Replacing the demo auth server with a commercial provider:
1. **Configure provider**: Set up OAuth app in Auth0/Okta
2. **Update metadata URL**: Point to provider's discovery endpoint
3. **Configure introspection**: Set up token validation
4. **Update redirect URIs**: Configure allowed callbacks
5. **Migrate users**: Import existing users if needed
6. **Test integration**: Verify full OAuth flow
---
## Best Practices
1. **Use separate servers** for production deployments

View file

@ -194,18 +194,6 @@ This ensures only the client that initiated the flow can exchange the code, even
---
## Architecture Benefits
The separate server architecture provides:
1. **Standards Compliance**: Follows OAuth 2.0 best practices for resource/authorization server separation
2. **Flexibility**: Auth server can be replaced with Auth0, Okta, or other providers
3. **Scalability**: Auth and MCP servers can scale independently based on load
4. **Security**: Token validation via introspection endpoint (RFC 7662)
5. **Maintainability**: Clear separation of authentication and business logic
---
## References
- [RFC 6749: OAuth 2.0 Framework](https://datatracker.ietf.org/doc/html/rfc6749)