vault backup: 2026-04-01 12:30:06
This commit is contained in:
150
07-Other/AI/AI Agent/WY/Website/Netease AITA AuthBridge.md
Normal file
150
07-Other/AI/AI Agent/WY/Website/Netease AITA AuthBridge.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# 提示词
|
||||
请你说中文,并使用中文编写文档。
|
||||
我打算使用使用Nodejs构建一个MCP SSE服务器,帮助OpenClaw以及其他Agent进行OIDC认证。并且编写对应的Skill,协助Agent使用该MCP。MCP 服务器充当了 **OIDC Client** 和 **凭证管理器**。
|
||||
|
||||
OIDC相关文档在./docs/Netease_OIDC.md,里面的链接可能需要认证,你可以打开浏览器等待我来帮你认证。
|
||||
#### 核心流程步骤:
|
||||
1. **触发**:Agent 在执行任务时发现需要访问 NetEase 内部接口。
|
||||
2. **调用 MCP**:Agent 调用 MCP 工具 `get_auth_url`。
|
||||
3. **生成状态**:MCP 生成一个随机 `state` 存入 MongoDB,并构建 OIDC 授权链接。
|
||||
4. **交互**:
|
||||
- **方案 A (手动)**:Agent 将链接发给用户,用户点击。
|
||||
- **方案 B (自动化)**:使用类似 `browser-use` 的 Skill,由 Agent 直接控制浏览器打开该链接,并等待用户在弹出的窗口中完成 SSO 登录。
|
||||
5. **回调**:用户登录成功后,NetEase OIDC 重定向到 MCP 的 Fastify 接口。
|
||||
6. **换取 Token**:MCP 后端用 `code` 换取 JWT,并将其与用户信息绑定存入 MongoDB。
|
||||
7. **通知/轮询**:Agent 通过 MCP 轮询或 SSE 得到“认证成功”状态,随后获取 JWT 进行业务操作。
|
||||
|
||||
---
|
||||
### 2. 技术实现细节
|
||||
#### 2.1 数据库设计 (Mongoose)
|
||||
主要用于维护认证状态和存储持久化的 Token。
|
||||
JavaScript
|
||||
```
|
||||
// models/AuthState.js
|
||||
const authStateSchema = new mongoose.Schema({
|
||||
state: { type: String, required: true, unique: true }, // 用于防止CSRF和匹配回调
|
||||
userId: { type: String, required: true }, // 对应 OpenClaw 的用户 ID
|
||||
status: { type: String, enum: ['pending', 'completed'], default: 'pending' },
|
||||
accessToken: String,
|
||||
idToken: String,
|
||||
refreshToken: String,
|
||||
expiresAt: Date,
|
||||
createdAt: { type: Date, expires: '10m', default: Date.now } // 10分钟后自动过期
|
||||
});
|
||||
```
|
||||
|
||||
#### 2.2 MCP 服务器核心逻辑 (Fastify + SSE)
|
||||
MCP 服务器需要同时支持 **SSE (与 Agent 通信)** 和 **HTTP (处理 OIDC 回调)**。
|
||||
- **MCP Tool: `get_netease_auth_url`** 输入:`userId` 输出:`authUrl`, `state` 逻辑:生成 OIDC URL,将 `state` 记录到 MongoDB。
|
||||
- **Fastify Route: `/api/callback`** 逻辑:
|
||||
1. 接收 `code` 和 `state`。
|
||||
2. 校验 `state` 是否在 MongoDB 中存在。
|
||||
3. 向 NetEase OIDC 换取 Token。
|
||||
4. 更新 MongoDB 中的状态为 `completed`。
|
||||
5. 通过 SSE 发送一个 `auth_success` 事件。
|
||||
#### 2.3 改进思路:自动化认证 (Browser-use 集成)
|
||||
当 OpenClaw(服务器端)与用户(本地客户端)不在同一台电脑时,直接调用系统命令(如 `open` 或 `start`)只会打开服务器端的浏览器,用户完全看不到。
|
||||
既然你提到用户开启了 **Chrome 远程调试模式 (`--remote-debugging-port=9222`)**,我们可以利用 **CDP (Chrome DevTools Protocol)** 协议来实现跨机器的“远程操控”。
|
||||
以下是针对你的 Node.js MCP 服务器的技术实现方案:
|
||||
|
||||
---
|
||||
##### 1. 核心架构:远程 CDP 连接
|
||||
要让运行在服务器上的 MCP 能够操控用户本地的 Chrome,流程如下:
|
||||
###### 挑战:网络连通性
|
||||
通常用户的电脑处于内网(NAT 之后),服务器无法直接访问用户的 `9222` 端口。
|
||||
- **方案 A (内网直连)**:如果两者在同一公司内网且 IP 互通,MCP 直接访问 `http://<User_IP>:9222`。
|
||||
- **方案 B (内网穿透)**:使用 `frp` 或 `ssh -R`。用户本地运行一个穿透工具,将本地的 `9222` 映射到服务器可见的某个端口(如服务器的 `19222`)。
|
||||
|
||||
---
|
||||
##### 2. 技术实现:MCP 服务器代码 (Node.js)
|
||||
在你的 Node.js 环境中,推荐使用 **Playwright**,因为它原生支持 `connectOverCDP`,非常适合这种场景。
|
||||
|
||||
###### 安装依赖
|
||||
```bash
|
||||
npm install playwright
|
||||
```
|
||||
|
||||
###### MCP 工具逻辑示例
|
||||
在 MCP 中编写一个 `open_remote_auth_page` 的工具:
|
||||
```ts
|
||||
import { chromium } from 'playwright';
|
||||
|
||||
async function openRemoteBrowser(userIp, authUrl) {
|
||||
// 1. 连接到用户本地开启了调试模式的浏览器
|
||||
// 假设通过穿透或直连,地址为 userIp:9222
|
||||
const browser = await chromium.connectOverCDP(`http://${userIp}:9222`);
|
||||
|
||||
// 2. 获取当前的上下文(通常是用户正开着的浏览器窗口)
|
||||
const defaultContext = browser.contexts()[0];
|
||||
const page = await defaultContext.newPage();
|
||||
|
||||
// 3. 导航到 NetEase OIDC 认证页面
|
||||
await page.goto(authUrl);
|
||||
|
||||
// 4. (可选) 监听 URL 跳转,自动化部分流程
|
||||
// 比如检测到跳转回 callback URL 时,自动告知 Agent
|
||||
page.on('framenavigated', frame => {
|
||||
const url = frame.url();
|
||||
if (url.includes('your-callback-url')) {
|
||||
console.log('用户已完成认证!');
|
||||
// 这里可以触发 MongoDB 状态更新或 SSE 通知
|
||||
}
|
||||
});
|
||||
|
||||
// 注意:不要执行 browser.close(),否则会关掉用户的整个 Chrome
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
##### 3. 针对用户的操作指南 (Skill 配合)
|
||||
为了让这个 Skill 成功运行,Agent 需要引导用户做两件事:
|
||||
1. **启动 Chrome 调试模式**: 用户需要在本地终端执行:
|
||||
```bash
|
||||
# macOS
|
||||
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
|
||||
```
|
||||
2. **提供 IP/端口信息**: Agent 可以询问用户:“请提供你本地机器的 IP 地址(或内网穿透后的地址)”。
|
||||
|
||||
---
|
||||
##### 4. 更优雅的改进方案:WebRTC 或轻量级“领航员”
|
||||
如果让用户手动输入 IP 比较繁琐,你可以编写一个 **“Claw-Bridge”**(一个几十行代码的本地 Node.js 脚本或 Go 小程序):
|
||||
- **工作原理**:
|
||||
1. 用户在本地运行 `Claw-Bridge`。
|
||||
2. `Claw-Bridge` 启动后通过 WebSocket 连接到你的 Fastify 服务器(建立长连接)。
|
||||
3. 当 MCP 需要打开网页时,向该 WebSocket 发送指令。
|
||||
4. `Claw-Bridge` 在用户本地执行 `open <URL>`。
|
||||
|
||||
**优点**:
|
||||
- **无需开启远程调试端口**(安全性更高,不会暴露浏览器的控制权给整个网络)。
|
||||
- **无需固定 IP**(只要有网络,长连接就能通)。
|
||||
- **权限最小化**:本地程序只负责“打开链接”,不涉及控制浏览器内部。
|
||||
##### 5. 总结建议
|
||||
- 如果你追求**深度自动化**(比如想让 Agent 帮用户自动填表):使用 **Playwright + CDP**。
|
||||
- 如果你只追求**方便用户点击**(仅仅是弹出一个认证页):编写一个轻量级的 **本地桥接脚本** 配合你的 Fastify 服务器,通过 WebSocket 转发“打开页面”的请求。
|
||||
---
|
||||
### 3. MCP Skill (工具定义) 示例
|
||||
在 MCP 服务器中定义的工具描述:
|
||||
```
|
||||
{
|
||||
"name": "authenticate_netease",
|
||||
"description": "当需要访问网易内部服务但未授权时使用。该工具会返回一个认证链接,必须引导用户完成认证。",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user_id": { "type": "string", "description": "当前用户的唯一标识" }
|
||||
},
|
||||
"required": ["user_id"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
### 4. 安全建议
|
||||
1. **PKCE (Proof Key for Code Exchange)**:既然是 Node.js 后端,务必开启 PKCE。在生成授权链接时生成 `code_verifier` 并存储在 MongoDB,回调时带上。
|
||||
2. **JWT 验证**:使用 `fastify-jwt` 验证从 OIDC 拿到的 `id_token` 的签名,确保其确实来自网易的认证服务。
|
||||
3. **State 绑定**:确保回调时的 `state` 只能被使用一次,防止重放攻击。
|
||||
4. **环境隔离**:建议在 MongoDB 中区分开发环境和生产环境的 `client_id`。
|
||||
## 技术选型
|
||||
我打算使用:
|
||||
后端技术:nodejs、Fastify、Mongoose、fastify-jwt
|
||||
数据库:MongoDB
|
||||
Reference in New Issue
Block a user