OAuth 2.1 proxy setup
ModGate implements the full OAuth 2.1 authorization code flow with PKCE and Dynamic Client Registration — exactly as required by the MCP specification. This page explains how it works and how to integrate it with your agent or client.
1. Discovery endpoint
Every ModGate deployment exposes a compliant OAuth 2.1 discovery endpoint. MCP clients that support the spec auto-discover everything they need from here — no manual configuration required.
GET https://api.modgate.io/.well-known/oauth-authorization-server
{
"issuer": "https://api.modgate.io",
"authorization_endpoint": "https://api.modgate.io/oauth/authorize",
"token_endpoint": "https://api.modgate.io/oauth/token",
"registration_endpoint": "https://api.modgate.io/oauth/register",
"scopes_supported": ["mcp:read","mcp:write","mcp:execute","mcp:admin"],
"code_challenge_methods_supported": ["S256"],
"grant_types_supported": ["authorization_code","refresh_token"]
}2. Dynamic Client Registration
ModGate supports RFC 7591 Dynamic Client Registration. AI agents and MCP clients register themselves programmatically — no manual client setup or pre-shared credentials required.
POST https://api.modgate.io/oauth/register
Content-Type: application/json
{
"client_name": "My AI Agent",
"redirect_uris": ["https://myapp.com/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"scope": "mcp:read mcp:execute",
"token_endpoint_auth_method": "none"
}
# Response:
{
"client_id": "client_abc123...",
"client_secret": null,
"client_name": "My AI Agent",
"redirect_uris": ["https://myapp.com/callback"]
}token_endpoint_auth_method to "none". PKCE is mandatory for all public clients.3. Authorization code flow with PKCE
ModGate uses PKCE (Proof Key for Code Exchange) with the S256 method. The full flow:
Step 1 — Generate PKCE values
# Generate a cryptographically random code verifier (43-128 chars)
code_verifier = base64url(random_bytes(32))
# Derive the code challenge
code_challenge = base64url(sha256(code_verifier))Step 2 — Redirect to authorization endpoint
GET https://api.modgate.io/oauth/authorize
?response_type=code
&client_id=client_abc123
&redirect_uri=https://myapp.com/callback
&scope=mcp:read mcp:execute
&code_challenge=BASE64URL_SHA256_OF_VERIFIER
&code_challenge_method=S256
&state=RANDOM_STATE_VALUEStep 3 — Exchange code for tokens
POST https://api.modgate.io/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://myapp.com/callback
&client_id=client_abc123
&code_verifier=ORIGINAL_CODE_VERIFIER
# Response:
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 900,
"refresh_token": "rt_...",
"scope": "mcp:read mcp:execute"
}Step 4 — Refresh access tokens
POST https://api.modgate.io/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=rt_...
&client_id=client_abc123Refresh is denied outright if the agent has been revoked or has expired. If the agent was force-reauthed by an admin after this refresh token was issued, refresh is also denied — you'll need a full new authorization_code exchange, not just a refresh, to clear a force-reauth. Refreshing is not itself a billable authentication — only the original authorization_code exchange and delegation issuance count toward your quota.
4. Scopes
| Scope | Description |
|---|---|
| mcp:read | Read-only access — list tools, read resources |
| mcp:write | Write access — create or update resources |
| mcp:execute | Execute tools — call any tool on the server |
| mcp:admin | Full admin access — use with caution |
Scopes are further constrained by agent-level policies. Even if a token has mcp:execute, an agent configured to only call read_contacts will be denied any other tool call. See Agent identity for per-tool policies.
5. Token introspection and revocation
Introspect a token
POST https://api.modgate.io/oauth/introspect
Content-Type: application/x-www-form-urlencoded
X-ModGate-API-Key: YOUR_API_KEY
token=eyJ...
# Response:
{
"active": true,
"sub": "agent_xyz",
"scope": "mcp:read mcp:execute",
"exp": 1735000000,
"aud": "mcp:your-tenant-id"
}Revoke a token
POST https://api.modgate.io/oauth/revoke
Content-Type: application/x-www-form-urlencoded
token=eyJ...
&client_id=client_abc123Revocation takes effect immediately for any request through the ModGate MCP proxy — every proxied call re-checks the agent's live status against its current stored state, not just the token's signature. Third-party resource servers calling /oauth/introspect get this same live check, so active correctly flips to false the moment an agent is revoked. Only a server that validates the JWT signature entirely on its own, without ever calling ModGate again, is limited to revocation-at-expiry — now a maximum of 15 minutes. Introspection itself is never a billable event.
6. Cross-agent delegation (xAA)
Orchestrator agents with delegation enabled can mint scoped tokens for sub-agents they spawn, without those sub-agents ever going through the authorization code flow themselves. The delegated token embeds a cryptographically verifiable chain back to the root authority.
POST https://api.modgate.io/oauth/delegate
Authorization: Bearer ORCHESTRATOR_ACCESS_TOKEN
Content-Type: application/json
{
"sub_agent": "agent_worker_42",
"scope": "mcp:read mcp:execute",
"ttl": 900
}
# Response:
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "mcp:read mcp:execute",
"delegation": {
"chain": ["agent_orchestrator_1", "agent_worker_42"],
"depth": 1,
"delegated_by": "agent_orchestrator_1"
}
}See Agent identity for the full delegation model, and Continuous authorization for how live session checks apply to orchestrators, not just their sub-agents.