CorpusIQ

RFC7591 Dynamic Client Registration Implementation

Overview

This document explains the RFC7591 (OAuth 2.0 Dynamic Client Registration Protocol) implementation added to resolve OpenAI MCP server integration issues.

Problem

When using a Cloudflare tunnel to expose your MCP server, OpenAI attempts to dynamically register itself as an OAuth client using RFC7591. Without this endpoint, OpenAI returns an error stating the server doesn’t support RFC7591.

Solution

Added full RFC7591 Dynamic Client Registration support to the MCP server.

Changes Made

1. Settings Configuration (src/corpusiq/settings.py)

Added new configuration options:

  • oauth_registration_endpoint: The URL where clients can register (default: https://your-domain.com/register)
  • allow_dynamic_client_registration: Boolean flag to enable/disable dynamic registration (default: True)

2. OAuth Metadata Updates (src/corpusiq/app.py)

Updated /.well-known/oauth-authorization-server endpoint to include:

  • registration_endpoint: Advertises the RFC7591 registration endpoint
  • token_endpoint_auth_methods_supported: Lists supported authentication methods

3. Client Registration Endpoint (src/corpusiq/app.py)

Implemented POST /register endpoint that:

  • Accepts client registration requests per RFC7591 specification
  • Validates required fields (redirect_uris, client_name, etc.)
  • Generates client credentials (client_id and client_secret if needed)
  • Returns RFC7591-compliant registration response with:
    • client_id: Unique identifier for the client
    • client_secret: Secret for client authentication (if applicable)
    • client_id_issued_at: Unix timestamp of registration
    • client_secret_expires_at: Expiration time (90 days)
    • All other client metadata

How It Works

Registration Flow

  1. OpenAI discovers the registration endpoint via /.well-known/oauth-authorization-server
  2. OpenAI sends a POST request to /register with:
    {
      "client_name": "OpenAI ChatGPT",
      "redirect_uris": ["https://chat.openai.com/callback"],
      "grant_types": ["authorization_code"],
      "response_types": ["code"],
      "token_endpoint_auth_method": "client_secret_basic"
    }
    
  3. Server validates the request and generates credentials
  4. Server responds with client credentials:
    {
      "client_id": "client_abc123...",
      "client_secret": "secret_xyz789...",
      "client_name": "OpenAI ChatGPT",
      "redirect_uris": ["https://chat.openai.com/callback"],
      "grant_types": ["authorization_code"],
      "response_types": ["code"],
      "token_endpoint_auth_method": "client_secret_basic",
      "scope": "corpus:read corpus:search",
      "client_id_issued_at": 1704240000,
      "client_secret_expires_at": 1711996800
    }
    

Environment Configuration

For Cloudflare Tunnel Setup

Update your .env file or environment variables:

# Your Cloudflare tunnel URL
CORPUSIQ_OAUTH_RESOURCE_URL=https://your-tunnel.trycloudflare.com

# Registration endpoint (usually the same as resource URL + /register)
CORPUSIQ_OAUTH_REGISTRATION_ENDPOINT=https://your-tunnel.trycloudflare.com/register

# OAuth issuer (can be the same as resource URL for self-contained servers)
CORPUSIQ_OAUTH_ISSUER=https://your-tunnel.trycloudflare.com

# OAuth endpoints (customize based on your auth provider)
CORPUSIQ_OAUTH_AUTHORIZATION_ENDPOINT=https://your-tunnel.trycloudflare.com/authorize
CORPUSIQ_OAUTH_TOKEN_ENDPOINT=https://your-tunnel.trycloudflare.com/token
CORPUSIQ_OAUTH_JWKS_URI=https://your-tunnel.trycloudflare.com/.well-known/jwks.json

# Enable dynamic client registration
CORPUSIQ_ALLOW_DYNAMIC_CLIENT_REGISTRATION=true

# CORS - allow OpenAI to access your server
CORPUSIQ_CORS_ALLOW_ORIGINS_CSV=https://chat.openai.com,https://chatgpt.com

Testing the Implementation

1. Test OAuth Metadata Discovery

curl https://your-tunnel.trycloudflare.com/.well-known/oauth-authorization-server

Should return JSON including:

{
  "registration_endpoint": "https://your-tunnel.trycloudflare.com/register",
  ...
}

2. Test Client Registration

curl -X POST https://your-tunnel.trycloudflare.com/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "Test Client",
    "redirect_uris": ["https://example.com/callback"],
    "grant_types": ["authorization_code"],
    "response_types": ["code"]
  }'

Should return 201 Created with client credentials.

3. Monitor Server Logs

When OpenAI connects, you should see log entries like:

Client registration request received: OpenAI ChatGPT
Client registered successfully: client_abc123... (OpenAI ChatGPT)
Client redirect URIs: ['https://chat.openai.com/callback']

Production Considerations

⚠️ Important: Client Storage

The current implementation generates credentials but does not persist them. For production:

  1. Add a database or key-value store to persist client credentials
  2. Implement client lookup during token exchange
  3. Add client secret validation in your token endpoint
  4. Consider using a proper OAuth provider like Auth0, Keycloak, or similar

Example Storage Implementation

# In production, replace the TODO comment with actual storage:
# Store in database
await db.clients.insert_one({
    "client_id": client_id,
    "client_secret": hashed_secret,  # Use bcrypt or similar
    "client_name": client_name,
    "redirect_uris": redirect_uris,
    "created_at": datetime.utcnow(),
    "expires_at": datetime.utcnow() + timedelta(days=90)
})

Security Notes

  1. Client secrets should be hashed before storage (use bcrypt, argon2, etc.)
  2. Validate redirect URIs strictly to prevent authorization code interception
  3. Use HTTPS only for all OAuth endpoints (enforced by Cloudflare tunnel)
  4. Rate limit the registration endpoint to prevent abuse (already included via RateLimitMiddleware)
  5. Consider requiring authentication for client registration in production
  6. Log all registration attempts for security auditing (already implemented)

Troubleshooting

OpenAI Still Reports RFC7591 Error

  1. Verify the metadata endpoint is accessible: /.well-known/oauth-authorization-server
  2. Check that registration_endpoint is present in the response
  3. Ensure your Cloudflare tunnel is properly forwarding requests
  4. Check server logs for any registration errors

403 Forbidden on /register

  • Verify CORPUSIQ_ALLOW_DYNAMIC_CLIENT_REGISTRATION=true is set
  • Check that the environment variable is being loaded correctly

400 Invalid Redirect URI

  • Ensure the client is sending at least one redirect_uri in the registration request
  • Validate that redirect URIs are properly formatted URLs

References