Securing MCP Connections with OAuth: Complete Guide
OAuth provides secure, standardized authorization for MCP connections. This guide covers implementation patterns and best practices. For where OAuth fits next to Bearer tokens at an MCP gateway, see How to connect an MCP client to your server and MCP firewall and gateway explained.
Why OAuth for MCP?
- Standardized Security: Industry-proven protocol
- Token-Based Access: No credentials in requests
- Fine-Grained Permissions: Scope-based access control
- User Delegation: Allow limited access without sharing credentials
OAuth Flow for MCP
1. Authorization Request
const authUrl = `https://auth.example.com/authorize?
client_id=${clientId}
&redirect_uri=${redirectUri}
&response_type=code
&scope=mcp:read mcp:write
&state=${securityToken}`;
2. Token Exchange
const tokenResponse = await fetch('https://auth.example.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `grant_type=authorization_code
&code=${authCode}
&client_id=${clientId}
&client_secret=${clientSecret}`
});
const { access_token, refresh_token } = await tokenResponse.json();
3. MCP Request with Token
const mcpRequest = {
tool: 'my_tool',
arguments: args,
authorization: `Bearer ${accessToken}`
};
Implementation Patterns
Server-to-Server (Client Credentials)
For machine-to-machine communication:
const serverAuth = {
grant_type: 'client_credentials',
client_id: 'mcp-server',
client_secret: 'server-secret',
scope: 'mcp:github mcp:jira'
};
User Delegation (Authorization Code)
For user-initiated actions:
const userAuth = {
grant_type: 'authorization_code',
code: authCode,
redirect_uri: callbackUrl,
client_id: clientId
};
Token Management
Refresh Tokens
const refreshAccessToken = async (refreshToken) => {
const response = await fetch(tokenEndpoint, {
method: 'POST',
body: `grant_type=refresh_token
&refresh_token=${refreshToken}
&client_id=${clientId}`
});
return response.json();
};
Token Revocation
const revokeToken = async (token) => {
await fetch(revokeEndpoint, {
method: 'POST',
body: `token=${token}`
});
};
Security Best Practices
- Use HTTPS: Always encrypt traffic
- Short-Lived Tokens: Minimize token lifetime
- Secure Storage: Store tokens encrypted
- Regular Rotation: Refresh tokens frequently
- Scope Limitation: Request minimum required scopes
Conclusion
OAuth is only as good as your token storage, rotation, and scope discipline. Treat refresh tokens like passwords; log auth failures; assume someone will try to replay an old token.
Related Articles
- How to connect an MCP client to your server - Headers, endpoints, gateways
- MCP firewall and gateway explained - Policy layer alongside OAuth
- MCP Security Best Practices - Practical security checklist
- How to Set Up GitHub MCP - OAuth implementation example
- How to Set Up Jira MCP - Another OAuth example
- Top 10 MCP Servers in 2026 - Discover MCP integrations
- MCP at Scale: Lessons from Production - Security at scale