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
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
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
Cloud Deployment
Self-Hosted (Optional)
# 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:
Mode OAuth Required Environment Variable Cloud/Production Yes EXECUTOR_DEPLOYMENT_MODE=cloudSelf-hosted No (optional) EXECUTOR_DEPLOYMENT_MODE=self-hostedUnset No (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
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
{
"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
# Fetch authorization server metadata
curl https://your-deployment.convex.site/.well-known/oauth-authorization-server
# Should proxy WorkOS metadata:
# {
# "issuer": "https://your-authkit-domain.authkit.app",
# "authorization_endpoint": "...",
# "token_endpoint": "...",
# "jwks_uri": "..."
# }
# Test with valid resource hint
curl "https://your-deployment.convex.site/.well-known/oauth-protected-resource?resource=https://your-deployment.convex.site/v1/mcp?workspaceId=xyz"
# Test with anonymous path (should fail)
curl "https://your-deployment.convex.site/.well-known/oauth-protected-resource?resource=https://your-deployment.convex.site/v1/mcp/anonymous"
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