{"slug":"strategy/product-strategy/MCP_OAUTH_ARCHITECTURE","title":"MCP OAuth 2.0 Architecture","section":"strategy","sectionLabel":"Strategy","status":"unclassified","type":"document","path":"strategy/product-strategy/MCP_OAUTH_ARCHITECTURE.mdx","bytes":5869,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n> Last updated: 2026-06-09\n> Classification: internal\n> Authority: Nirmal (Founder)\n\n---\n\n## Overview\n\n- MCP connector (`mcp.integratewise.ai`) owns the OAuth 2.0 authorization server\n- MCP protocol endpoint is the root: `POST https://mcp.integratewise.ai/` — `/mcp` is kept for backward compatibility only\n- Gateway (`auth.integratewise.ai`) proxies OAuth traffic to MCP connector via service binding\n- Both subdomains serve the same OAuth flow — MCP holds the crypto keys\n- RS256 JWT tokens signed with shared key pair (`gateway/src/lib/jwt.ts`)\n\n---\n\n## Deployment Status (June 9, 2026)\n\n- MCP Connector deployed: Version eb8137b4-99fd-4cd3-bb81-311caa3bd6f1\n- Gateway deployed: Version 329b3793-c4d8-48e1-bec1-b47a50c5848a\n- D1 Migration applied: oauth_clients, oauth_refresh_tokens, oauth_revocations tables live\n- Token issuance verified: client_credentials grant working end-to-end\n- MCP tools/list verified: 18 tools returned via authenticated POST /\n\n---\n\n## Domain Responsibilities\n\n| Subdomain               | Auth Type                    | Audience                                         |\n| ----------------------- | ---------------------------- | ------------------------------------------------ |\n| `auth.integratewise.ai` | Gateway proxies to MCP OAuth | AI agents via browser consent                    |\n| `mcp.integratewise.ai`  | Native OAuth 2.0 endpoints   | AI agents direct (Claude, ChatGPT, Cursor, Kiro) |\n\n---\n\n## OAuth Endpoints (served by MCP connector)\n\n- `POST /` — MCP JSON-RPC protocol (primary endpoint)\n- `POST /mcp` — MCP JSON-RPC protocol (backward compatibility)\n- `GET /.well-known/oauth-authorization-server` — discovery metadata\n- `GET /.well-known/oauth-protected-resource` — protected resource metadata\n- `GET /.well-known/jwks.json` — public key for token verification\n- `GET /oauth/authorize` — consent page (renders HTML form)\n- `POST /oauth/authorize/confirm` — form submission → issues auth code\n- `POST /oauth/token` — exchanges code/credentials/refresh_token for JWT\n- `POST /oauth/revoke` — RFC 7009 token revocation\n\n---\n\n## Supported Grant Types\n\n1. `authorization_code` — interactive consent flow for AI clients\n2. `client_credentials` — machine-to-machine (no user interaction)\n3. `refresh_token` — rotate access without re-authorization (30-day TTL)\n\n---\n\n## Token Format\n\n- RS256 JWT (asymmetric — public key in JWKS, private key in Worker secrets)\n- Claims: `iss`, `aud`, `sub`, `tenant_id`, `role`, `scope`, `exp`, `iat`\n- Access token TTL: 1 hour\n- Refresh token TTL: 30 days (stored hashed in D1, rotated on use)\n\n---\n\n## Scope Enforcement\n\nScopes map to MCP tool access:\n\n- `mcp:tools` — superscope, grants access to all tools\n- `mcp:resources` — read-only access to Spine entities, signals, proposals\n- `tenant:read` / `tenant:write` — tenant-scoped data access\n- `memory:read` / `memory:write` — memory layer access\n\nTool-level enforcement in `oauth-scopes.ts` — `tools/list` response is filtered to visible tools based on token scope.\n\n---\n\n## Client Registry (D1)\n\n- Table: `oauth_clients` in `integratewise-spine-cache`\n- Fields: `client_id`, `client_secret_hash` (SHA-256), `redirect_uris`, `allowed_scopes`, `grant_types`\n- Validation: redirect_uri allowlist, scope intersection, grant_type restriction\n- Registration: via `scripts/register-oauth-client.ts` or direct D1 SQL\n\n---\n\n## Refresh Token Storage (D1)\n\n- Table: `oauth_refresh_tokens` in `integratewise-spine-cache`\n- Tokens stored as SHA-256 hashes (plaintext never persisted)\n- Rotation: old token revoked when new one is issued\n- Revocation audit: `oauth_revocations` table\n\n---\n\n## Gateway Integration\n\n- Gateway validates MCP tokens at the edge (signature + expiry check via `verifyJWT`)\n- Enriches requests with `x-tenant-id`, `x-user-id`, `x-user-role`, `x-oauth-scope` headers\n- Forwards to MCP connector via `CONNECTOR` service binding\n- If Gateway is down, MCP connector still serves OAuth directly on `mcp.integratewise.ai`\n\n---\n\n## Auth Cascade (MCP connector verifyAuth)\n\nPriority order:\n\n1. Service binding (`cf-worker` header) → Admin role\n2. Cloudflare Access JWT (`CF-Access-JWT-Assertion`) → Member role\n3. IntegrateWise OAuth JWT (`iss` contains \"integratewise.\") → role from token + scope\n4. Triage Bot API key → TriageBot + Admin roles\n5. MCP Connector API key → Admin role\n6. Supabase JWT → tenant from claims\n\n---\n\n## Migration\n\nDeploy D1 schema:\n\n```bash\nwrangler d1 execute integratewise-spine-cache --file services/mcp-connector/migrations/0001_oauth_tables.sql\n```\n\n---\n\n## Client Configuration (Claude Desktop example)\n\n```json\n{\n  \"mcpServers\": {\n    \"integratewise\": {\n      \"url\": \"https://mcp.integratewise.ai\",\n      \"auth\": {\n        \"type\": \"oauth2\",\n        \"client_id\": \"claude-desktop-iw\",\n        \"client_secret\": \"your-secret\",\n        \"authorize_url\": \"https://mcp.integratewise.ai/oauth/authorize\",\n        \"token_url\": \"https://mcp.integratewise.ai/oauth/token\",\n        \"scope\": \"mcp:tools mcp:resources memory:read\"\n      }\n    }\n  }\n}\n```\n\n---\n\n## Files\n\n- `services/mcp-connector/src/lib/oauth-auth-server.ts` — authorization server (consent, token exchange)\n- `services/mcp-connector/src/lib/oauth-clients.ts` — D1 client registry\n- `services/mcp-connector/src/lib/oauth-refresh.ts` — refresh token management\n- `services/mcp-connector/src/lib/oauth-scopes.ts` — scope-to-tool enforcement\n- `services/mcp-connector/src/lib/oauth-middleware.ts` — resource server middleware\n- `services/mcp-connector/src/lib/oauth-constants.ts` — scopes, path detection, WWW-Authenticate\n- `services/mcp-connector/migrations/0001_oauth_tables.sql` — D1 schema\n- `services/gateway/src/lib/jwt.ts` — RS256 sign/verify (shared key pair)\n- `services/gateway/src/index.ts` — OAuth proxy for auth.integratewise.ai\n"}