Skip to main content
Executor implements OAuth 2.0 discovery metadata endpoints to enable MCP clients to discover and authenticate with protected resources.

Overview

The OAuth integration provides:
  • Protected resource discovery - Metadata about the MCP resource and its authorization servers
  • Authorization server proxy - Proxied metadata from WorkOS AuthKit
  • Bearer token authentication - Standard OAuth 2.0 bearer token flow
OAuth is required for authenticated MCP endpoints in cloud deployments. Self-hosted deployments can optionally disable OAuth.

Endpoints

Protected Resource Metadata

GET /.well-known/oauth-protected-resource
Returns metadata about the protected MCP resource. Query Parameters:
  • resource (optional) - Resource hint URL to validate
Response:
{
  "resource": "https://your-deployment.convex.site/v1/mcp?workspaceId=xyz",
  "authorization_servers": [
    "https://your-authkit-domain.authkit.app"
  ],
  "bearer_methods_supported": ["header"]
}
Example:
curl https://your-deployment.convex.site/.well-known/oauth-protected-resource

Authorization Server Metadata

GET /.well-known/oauth-authorization-server
Proxies the upstream WorkOS AuthKit OAuth 2.0 metadata. Response: Forwards the response from:
https://your-authkit-domain.authkit.app/.well-known/oauth-authorization-server
Example:
curl https://your-deployment.convex.site/.well-known/oauth-authorization-server

Configuration

Environment Variables

# Required for cloud deployments
EXECUTOR_DEPLOYMENT_MODE=cloud

# WorkOS AuthKit configuration
MCP_AUTHORIZATION_SERVER=https://your-authkit-domain.authkit.app
WORKOS_CLIENT_ID=client_...
WORKOS_API_KEY=sk_...

Deployment Modes

The OAuth requirement depends on deployment mode:
ModeOAuth RequiredEnvironment Variable
Cloud/ProductionYesEXECUTOR_DEPLOYMENT_MODE=cloud
Self-hostedNo (optional)EXECUTOR_DEPLOYMENT_MODE=self-hosted
UnsetNo (optional)Can enable with EXECUTOR_ENFORCE_MCP_AUTH=1

Authentication Flow

1. Discovery

MCP client discovers the protected resource:
GET /.well-known/oauth-protected-resource?resource=https://your-deployment.convex.site/v1/mcp

2. Authorization Server Metadata

Client fetches authorization server capabilities:
GET /.well-known/oauth-authorization-server

3. Token Acquisition

Client obtains access token from WorkOS AuthKit using standard OAuth 2.0 flow.

4. MCP Request

Client includes bearer token in MCP requests:
POST /v1/mcp?workspaceId=xyz
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

5. Token Verification

Executor verifies the JWT token:
  • Issuer: Must match configured authorization server
  • Signature: Validated against JWKS from {authServer}/oauth2/jwks
  • Subject: Mapped to WorkOS user account
  • Provider claim: Must not be anonymous
WorkOS AuthKit tokens use the requesting client’s client ID as the audience, which varies per client. Executor only validates issuer and signature, not audience.

Resource Hints

The protected resource endpoint supports resource hints to validate the requesting URL:
GET /.well-known/oauth-protected-resource?resource=https://your-deployment.convex.site/v1/mcp?workspaceId=xyz
Validation:
  • Resource hint origin must match server origin
  • Anonymous MCP paths (/v1/mcp/anonymous) are rejected
  • Valid paths: /v1/mcp, /mcp (legacy)

Error Responses

OAuth Not Configured

{
  "error": "MCP OAuth is not configured"
}
Status: 404 (self-hosted) or 503 (cloud)

OAuth Required

{
  "error": "MCP OAuth must be configured for cloud deployments"
}
Status: 503

Invalid Resource Hint

{
  "error": "resource hint origin must match this server"
}
Status: 400

Unauthorized Request

{
  "error": "No valid bearer token provided."
}
Status: 401
Headers:
WWW-Authenticate: Bearer error="unauthorized", error_description="Authorization needed", resource_metadata="https://..."

Integration with WorkOS

Executor uses WorkOS AuthKit for user authentication and JWT token issuance:

Token Claims

Expected JWT structure:
{
  "iss": "https://your-authkit-domain.authkit.app",
  "sub": "user_...",
  "aud": "client_...",
  "provider": "workos",
  "exp": 1234567890,
  "iat": 1234567890
}

JWKS Endpoint

Executor fetches public keys from:
https://your-authkit-domain.authkit.app/oauth2/jwks

Workspace Authorization

After token verification, Executor checks workspace access:
const access = await getWorkspaceAccessForWorkosSubject({
  workspaceId: "wks_...",
  subject: "user_..."
});

Testing

# Verify OAuth discovery is configured
curl -i https://your-deployment.convex.site/.well-known/oauth-protected-resource

# Should return 200 with metadata if configured
# Returns 503/404 if OAuth not configured

Legacy Paths

Executor supports legacy MCP paths for backward compatibility:
  • /mcp - Legacy authenticated endpoint
  • /mcp/anonymous - Legacy anonymous endpoint
New integrations should use:
  • /v1/mcp - Current authenticated endpoint
  • /v1/mcp/anonymous - Current anonymous endpoint

Source Files

  • executor/packages/database/convex/http/oauth_handlers.ts - OAuth endpoint handlers
  • executor/packages/database/convex/http/mcp_auth.ts - Authentication and verification logic
  • executor/packages/database/convex/http.ts - Route registration

Build docs developers (and LLMs) love