Files
BlueRoseNote/07-Other/AI/AI Agent/WY/Website/Netease AITA AuthBridge.md

151 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 提示词
请你说中文,并使用中文编写文档。
我打算使用使用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