Skip to content

Commit 8976cbd

Browse files
authored
Merge pull request modelcontextprotocol#387 from modelcontextprotocol/pcarleton-security-considerations
[spec] Auth: consolidate security considerations into new section
2 parents c82be9c + 3e72c0f commit 8976cbd

File tree

3 files changed

+156
-34
lines changed

3 files changed

+156
-34
lines changed

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@
188188
"specification/draft/basic/lifecycle",
189189
"specification/draft/basic/transports",
190190
"specification/draft/basic/authorization",
191+
"specification/draft/basic/security_best_practices",
191192
{
192193
"group": "Utilities",
193194
"pages": [

docs/specification/draft/basic/authorization.mdx

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ as described in OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatra
9999

100100
MCP clients **MUST** be able to parse `WWW-Authenticate` headers and respond appropriately to `HTTP 401 Unauthorized` responses from the MCP server.
101101

102-
103102
#### 2.3.2 Server Metadata Discovery
104103

105104
MCP clients **MUST** follow the OAuth 2.0 Authorization Server Metadata protocol defined
@@ -247,17 +246,8 @@ own resources.
247246

248247
MCP servers **MUST NOT** accept or transit any other tokens.
249248

250-
### 2.8 Security Considerations
251-
252-
The following security requirements **MUST** be implemented:
253249

254-
1. Clients **MUST** securely store tokens following OAuth 2.0 best practices
255-
2. Servers **SHOULD** enforce token expiration and rotation
256-
3. All authorization endpoints **MUST** be served over HTTPS
257-
4. Servers **MUST** validate redirect URIs to prevent open redirect vulnerabilities
258-
5. Redirect URIs **MUST** be either localhost URLs or HTTPS URLs
259-
260-
### 2.9 Error Handling
250+
### 2.8 Error Handling
261251

262252
Servers **MUST** return appropriate HTTP status codes for authorization errors:
263253

@@ -267,35 +257,50 @@ Servers **MUST** return appropriate HTTP status codes for authorization errors:
267257
| 403 | Forbidden | Invalid scopes or insufficient permissions |
268258
| 400 | Bad Request | Malformed authorization request |
269259

270-
### 2.10 Implementation Requirements
260+
## 3. Security Considerations
261+
262+
Implementations **MUST** follow OAuth 2.1 security best practices as laid out in [Section 7. Security Considerations](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#name-security-considerations).
263+
264+
### 3.1 Token Theft
265+
Attackers who obtain tokens stored by the client, or tokens cached or logged on the server can access protected resources with
266+
requests that appear legitimate to resource servers.
267+
268+
Clients **MUST** implement secure token storage and follow OAuth best practices,
269+
as outlined in [OAuth 2.1, section 7.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-7.1).
270+
271+
MCP authorization servers SHOULD issue short-lived access tokens token to reduce the impact of leaked tokens. For public clients, MCP authorization servers MUST rotate refresh tokens as described in [Section 4.3.1 of OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-4.3.1).
272+
273+
### 3.2 Communication Security
274+
Implementations MUST follow [OAuth 2.1 section 1.5](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-1.5).
275+
276+
Specifically:
277+
1. All authorization server endpoints **MUST** be served over HTTPS.
278+
1. All redirect URIs **MUST** be either `localhost` or use HTTPS.
279+
280+
### 3.3 Authorization Code Protection
281+
282+
An attacker who has gained access to an authorization code contained in an authorization response can try to redeem the authorization code for an access token or otherwise make use of the authorization code. (Further described in [OAuth 2.1, section 7.5](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-7.5))
283+
284+
MCP clients **MUST** implement PKCE according to [OAuth 2.1 section 7.5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-7.5.2). PKCE helps prevent authorization code interception and injection attacks by requiring clients to create a secret verifier-challenge pair, ensuring that only the original requestor can exchange an authorization code for tokens.
285+
271286

272-
1. Implementations **MUST** follow OAuth 2.1 security best practices
273-
1. PKCE is **REQUIRED** for all MCP clients and authorization servers
274-
1. MCP servers that also act as an AS:
275-
1. **SHOULD** implement token rotation for enhanced security
276-
1. **SHOULD** restrict token lifetimes based on security requirements
287+
### 3.3 Open Redirection
288+
An attacker may craft malicious redirect URIs to direct users to phishing sites.
277289

278-
## 3. Best Practices
290+
MCP clients **MUST** have redirect URIs registered with the authorization server.
279291

280-
#### 3.1 Local clients as Public OAuth 2.1 Clients
292+
Authorization servers **MUST** validate exact redirect URIs against pre-registered values to prevent redirection attacks.
281293

282-
We strongly recommend that local clients implement OAuth 2.1 as a public client:
294+
MCP clients **SHOULD** use and verify state parameters in the authorization code flow
295+
and discard any results that do not include or have a mis-match with the original state.
283296

284-
1. Utilizing code challenges (PKCE) for authorization requests to prevent interception
285-
attacks
286-
2. Implementing secure token storage appropriate for the local system
287-
3. Following token refresh best practices to maintain sessions
288-
4. Properly handling token expiration and renewal
297+
Authorization servers **MUST** take precautions to prevent redirecting user agents to untrusted URI's, following suggestions laid out in [OAuth 2.1, Section 7.12.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-7.12.2)
289298

290-
#### 3.2 Authorization Metadata Discovery
299+
Authorization servers **SHOULD** only automatically redirect the user agent if it trusts the redirection URI. If the URI is not trusted, the authorization server MAY inform the user and rely on the user to make the correct decision.
291300

292-
We strongly recommend that all clients implement metadata discovery. This reduces the
293-
need for users to provide endpoints manually or clients to fallback to the defined
294-
defaults.
301+
### 3.4 Confused Deputy Problem
295302

296-
#### 3.3 Dynamic Client Registration
303+
Attackers can exploit MCP servers acting as intermediaries to third-party APIs, leading to confused deputy vulnerabilities. By using stolen authorization codes, they can obtain access tokens without user consent. See [Security Best Practices 2.1](/specification/draft/basic/security_best_practices) for details.
297304

298-
Since clients do not know the set of MCP servers in advance, we strongly recommend the
299-
implementation of dynamic client registration. This allows applications to automatically
300-
register with the MCP server, and removes the need for users to obtain client ids
301-
manually.
305+
MCP proxy servers using static client IDs **MUST** obtain user consent for each dynamically
306+
registered client before forwarding to third-party authorization servers (which may require additional consent).
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
title: Security Best Practices
3+
---
4+
5+
## 1. Introduction
6+
7+
### 1.1 Purpose and Scope
8+
9+
This document provides security considerations for the Model Context Protocol (MCP), complementing the MCP Authorization specification. This document identifies security risks, attack vectors, and best practices specific to MCP implementations.
10+
11+
The primary audience for this document includes developers implementing MCP authorization flows, MCP server operators, and security professionals evaluating MCP-based systems. This document should be read alongside the MCP Authorization specification and [OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700).
12+
13+
## 2. Attacks and Mitigations
14+
15+
This section gives a detailed description of attacks on MCP implementations, along with potential countermeasures.
16+
17+
### 2.1 Confused Deputy Problem
18+
19+
Attackers can exploit MCP servers proxying other resource servers, creating "[confused deputy](https://en.wikipedia.org/wiki/Confused_deputy_problem)" vulnerabilities.
20+
21+
#### 2.1.1 Terminology
22+
23+
**MCP Proxy Server**
24+
: An MCP server that connects MCP clients to third-party APIs, offering MCP features while delegating operations and acting as a single OAuth client to the third-party API server.
25+
26+
**Third-Party Authorization Server**
27+
: Authorization server that protects the third-party API. It may lack dynamic client registration support, requiring MCP proxy to use a static client ID for all requests.
28+
29+
**Third-Party API**
30+
: The protected resource server that provides the actual API functionality. Access to this
31+
API requires tokens issued by the third-party authorization server.
32+
33+
**Static Client ID**
34+
: A fixed OAuth 2.0 client identifier used by the MCP proxy server when communicating with
35+
the third-party authorization server. This Client ID refers to the MCP server acting as a client
36+
to the Third-Party API. It is the same value for all MCP server to Third-Party API interactions regardless of
37+
which MCP client initiated the request.
38+
39+
#### 2.1.2 Architecture and Attack Flows
40+
41+
##### 2.1.2.1 Normal OAuth proxy usage (preserves user consent)
42+
43+
```mermaid
44+
sequenceDiagram
45+
participant UA as User-Agent (Browser)
46+
participant MC as MCP Client
47+
participant M as MCP Proxy Server
48+
participant TAS as Third-Party Authorization Server
49+
50+
Note over UA,M: Initial Auth flow completed
51+
52+
Note over UA,TAS: Step 1: Legitimate user consent for Third Party Server
53+
54+
M->>UA: Redirect to third party authorization server
55+
UA->>TAS: Authorization request (client_id: mcp-proxy)
56+
TAS->>UA: Authorization consent screen
57+
Note over UA: Review consent screen
58+
UA->>TAS: Approve
59+
TAS->>UA: Set consent cookie for client ID: mcp-proxy
60+
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
61+
UA->>M: 3P Authorization code
62+
Note over M,TAS: Exchange 3P code for 3P token
63+
Note over M: Generate MCP authorization code
64+
M->>UA: Redirect to MCP Client with MCP authorization code
65+
66+
Note over M,UA: Exchange code for token, etc.
67+
```
68+
69+
##### 2.1.2.3 Malicious OAuth proxy usage (skips user consent)
70+
71+
```mermaid
72+
sequenceDiagram
73+
participant UA as User-Agent (Browser)
74+
participant M as MCP Proxy Server
75+
participant TAS as Third-Party Authorization Server
76+
participant A as Attacker
77+
78+
79+
Note over UA,A: Step 2: Attack (leveraging existing cookie, skipping consent)
80+
A->>M: Dynamically register malicious client, redirect_uri: attacker.com
81+
A->>UA: Sends malicious link
82+
UA->>TAS: Authorization request (client_id: mcp-proxy) + consent cookie
83+
rect rgba(255, 17, 0, 0.67)
84+
TAS->>TAS: Cookie present, consent skipped
85+
end
86+
87+
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
88+
UA->>M: 3P Authorization code
89+
Note over M,TAS: Exchange 3P code for 3P token
90+
Note over M: Generate MCP authorization code
91+
M->>UA: Redirect to attacker.com with MCP Authorization code
92+
UA->>A: MCP Authorization code delivered to attacker.com
93+
Note over M,A: Attacker exchanges MCP code for MCP token
94+
A->>M: Attacker impersonates user to MCP server
95+
```
96+
97+
#### 2.1.3 Attack Description
98+
99+
When an MCP proxy server uses a static client ID to authenticate with a third-party
100+
authorization server that does not support dynamic client registration, the following
101+
attack becomes possible:
102+
103+
1. A user authenticates normally through the MCP proxy server to access the third-party API
104+
2. During this flow, the third-party authorization server sets a cookie on the user agent
105+
indicating consent for the static client ID
106+
3. An attacker later sends the user a malicious link containing a crafted authorization request which contains a malicious redirect URI along with a new dynamically registered client ID
107+
4. When the user clicks the link, their browser still has the consent cookie from the previous legitimate request
108+
5. The third-party authorization server detects the cookie and skips the consent screen
109+
6. The MCP authorization code is redirected to the attacker's server (specified in the crafted redirect_uri during dynamic client registration)
110+
7. The attacker exchanges the stolen authorization code for access tokens for the MCP server without the user's explicit approval
111+
8. Attacker now has access to the third-party API as the compromised user
112+
113+
#### 2.1.4 Mitigation
114+
115+
MCP proxy servers using static client IDs **MUST** obtain user consent for each dynamically
116+
registered client before forwarding to third-party authorization servers (which may require additional consent).

0 commit comments

Comments
 (0)