Skip to content

授权

模型上下文协议 (MCP) 的授权机制确保只有经过验证的客户端才能访问服务器资源和功能。

概述

MCP 授权基于以下原则:

  • 最小权限: 客户端只获得必要的权限
  • 明确授权: 所有访问都需要明确的授权
  • 可撤销性: 权限可以随时撤销
  • 审计性: 所有授权操作都可以被审计

授权模型

权限类型

工具权限

json
{
  "tools": {
    "allowed": ["file_read", "file_write"],
    "denied": ["system_exec"]
  }
}

资源权限

json
{
  "resources": {
    "allowed": ["file:///*", "http://api.example.com/*"],
    "denied": ["file:///etc/*", "file:///root/*"]
  }
}

提示权限

json
{
  "prompts": {
    "allowed": ["code_review", "documentation"],
    "denied": ["sensitive_data"]
  }
}

授权流程

1. 初始化阶段授权

mermaid
sequenceDiagram
    participant C as 客户端
    participant S as 服务器
    
    C->>S: initialize (包含客户端信息)
    S->>S: 验证客户端身份
    S->>S: 确定授权范围
    S->>C: initialized (包含授权信息)
    
    Note over C,S: 后续请求基于此授权

初始化请求示例

json
{
  "jsonrpc": "2.0",
  "method": "initialize",
  "id": 1,
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {},
      "resources": {},
      "prompts": {}
    },
    "clientInfo": {
      "name": "MyMCPClient",
      "version": "1.0.0"
    },
    "authorization": {
      "type": "api_key",
      "credentials": "sk-1234567890abcdef"
    }
  }
}

初始化响应示例

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {
        "listChanged": true
      },
      "resources": {
        "subscribe": true,
        "listChanged": true
      },
      "prompts": {
        "listChanged": true
      }
    },
    "serverInfo": {
      "name": "MyMCPServer",
      "version": "1.0.0"
    },
    "authorization": {
      "granted": {
        "tools": ["file_read", "file_write"],
        "resources": ["file://workspace/*"],
        "prompts": ["code_review"]
      },
      "denied": {
        "tools": ["system_exec"],
        "resources": ["file:///etc/*"],
        "prompts": ["sensitive_data"]
      }
    }
  }
}

2. 运行时授权检查

每个请求都会进行授权检查:

json
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": 2,
  "params": {
    "name": "file_read",
    "arguments": {
      "path": "/workspace/config.json"
    }
  }
}

服务器检查:

  1. 工具 file_read 是否在允许列表中
  2. 路径 /workspace/config.json 是否符合资源权限
  3. 客户端是否仍有有效授权

授权方法

1. API 密钥授权

json
{
  "authorization": {
    "type": "api_key",
    "credentials": "sk-1234567890abcdef"
  }
}

特点:

  • 简单易用
  • 适合服务器到服务器通信
  • 需要安全存储密钥

2. JWT 令牌授权

json
{
  "authorization": {
    "type": "jwt",
    "credentials": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}

JWT 载荷示例:

json
{
  "sub": "client_123",
  "iss": "mcp_auth_server",
  "aud": "mcp_server",
  "exp": 1640995200,
  "iat": 1640908800,
  "permissions": {
    "tools": ["file_read", "file_write"],
    "resources": ["file://workspace/*"],
    "prompts": ["code_review"]
  }
}

3. OAuth 2.0 授权

json
{
  "authorization": {
    "type": "oauth2",
    "credentials": "Bearer ya29.a0ARrdaM..."
  }
}

OAuth 流程:

  1. 客户端重定向到授权服务器
  2. 用户授权
  3. 获取访问令牌
  4. 使用令牌访问 MCP 服务器

4. 相互 TLS (mTLS)

json
{
  "authorization": {
    "type": "mtls",
    "client_cert_fingerprint": "sha256:1234567890abcdef..."
  }
}

特点:

  • 最高安全级别
  • 基于证书的双向认证
  • 适合企业环境

权限管理

权限继承

json
{
  "permissions": {
    "base": "read_only",
    "additional": {
      "tools": ["file_write"],
      "resources": ["file://temp/*"]
    }
  }
}

动态权限

json
{
  "jsonrpc": "2.0",
  "method": "authorization/request",
  "id": 3,
  "params": {
    "permissions": {
      "tools": ["system_exec"],
      "reason": "需要执行构建脚本"
    }
  }
}

权限撤销

json
{
  "jsonrpc": "2.0",
  "method": "authorization/revoke",
  "id": 4,
  "params": {
    "permissions": {
      "tools": ["file_write"]
    }
  }
}

实现示例

Python 服务器授权

python
from typing import Dict, List, Optional
import jwt
import time

class MCPAuthorizer:
    def __init__(self, secret_key: str):
        self.secret_key = secret_key
        self.active_sessions: Dict[str, Dict] = {}
    
    def authorize_client(self, auth_data: Dict) -> Optional[Dict]:
        """授权客户端并返回权限"""
        auth_type = auth_data.get("type")
        credentials = auth_data.get("credentials")
        
        if auth_type == "api_key":
            return self._authorize_api_key(credentials)
        elif auth_type == "jwt":
            return self._authorize_jwt(credentials)
        else:
            return None
    
    def _authorize_api_key(self, api_key: str) -> Optional[Dict]:
        """API 密钥授权"""
        # 验证 API 密钥
        if not self._validate_api_key(api_key):
            return None
        
        # 返回权限
        return {
            "tools": ["file_read", "file_write"],
            "resources": ["file://workspace/*"],
            "prompts": ["code_review"]
        }
    
    def _authorize_jwt(self, token: str) -> Optional[Dict]:
        """JWT 令牌授权"""
        try:
            payload = jwt.decode(token, self.secret_key, algorithms=["HS256"])
            
            # 检查过期时间
            if payload.get("exp", 0) < time.time():
                return None
            
            return payload.get("permissions", {})
        except jwt.InvalidTokenError:
            return None
    
    def check_permission(self, session_id: str, resource_type: str, resource_name: str) -> bool:
        """检查权限"""
        session = self.active_sessions.get(session_id)
        if not session:
            return False
        
        permissions = session.get("permissions", {})
        allowed = permissions.get(resource_type, [])
        
        return resource_name in allowed

TypeScript 客户端授权

typescript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';

class AuthorizedMCPClient {
    private client: Client;
    private authToken: string;
    
    constructor(authToken: string) {
        this.authToken = authToken;
        this.client = new Client({
            name: "authorized-client",
            version: "1.0.0"
        }, {
            capabilities: {}
        });
    }
    
    async connect(transport: any) {
        // 连接到服务器
        await this.client.connect(transport);
        
        // 发送授权信息
        const result = await this.client.request({
            method: "initialize",
            params: {
                protocolVersion: "2025-06-18",
                capabilities: {},
                clientInfo: {
                    name: "authorized-client",
                    version: "1.0.0"
                },
                authorization: {
                    type: "jwt",
                    credentials: this.authToken
                }
            }
        });
        
        // 存储授权信息
        this.storeAuthorization(result.authorization);
    }
    
    private storeAuthorization(auth: any) {
        // 存储授权信息以供后续使用
        console.log("授权成功:", auth);
    }
}

安全最佳实践

1. 令牌管理

  • 使用短期令牌
  • 实现令牌刷新机制
  • 安全存储令牌

2. 权限最小化

  • 只授予必要权限
  • 定期审查权限
  • 实现权限过期

3. 审计日志

json
{
  "timestamp": "2024-01-15T10:30:00Z",
  "client_id": "client_123",
  "action": "tools/call",
  "resource": "file_read",
  "result": "granted",
  "details": {
    "path": "/workspace/config.json"
  }
}

4. 错误处理

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "权限不足",
    "data": {
      "required_permission": "file_write",
      "current_permissions": ["file_read"]
    }
  }
}

相关资源

🚀 探索模型上下文协议的无限可能 | 连接 AI 与世界的桥梁 | 让智能更智能