|
| 1 | +--- |
| 2 | +name: OAuth2 Login Plugin |
| 3 | +overview: 在 设置->系统配置 中增加 OAuth2 插件配置,支持 GitHub 及自定义 OAuth2 服务器。默认关闭,开启后实现基于 OAuth 2.0 协议的用户登录鉴权,与现有逻辑完全向前兼容。 |
| 4 | +todos: |
| 5 | + - id: schema-oauth2 |
| 6 | + content: 在 derisk_core config schema 中新增 OAuth2ProviderConfig、OAuth2Config,扩展 AppConfig |
| 7 | + status: completed |
| 8 | + - id: user-ddl |
| 9 | + content: 扩展 user 表 DDL(oauth_provider、oauth_id、email、avatar) |
| 10 | + status: completed |
| 11 | + - id: auth-module |
| 12 | + content: 新建 derisk_app/auth 模块(OAuth 流程、session 管理、用户服务) |
| 13 | + status: completed |
| 14 | + - id: auth-api |
| 15 | + content: 新建 auth_api.py,实现 login/callback/me/logout 路由,并注册到 api_v1 |
| 16 | + status: completed |
| 17 | + - id: config-api-oauth2 |
| 18 | + content: 扩展 config_api 支持 oauth2 配置读写 |
| 19 | + status: completed |
| 20 | + - id: settings-oauth2-card |
| 21 | + content: 在 settings/config 页 VisualConfig 中新增 OAuth2 插件配置 Card |
| 22 | + status: completed |
| 23 | + - id: login-page |
| 24 | + content: 新建 /login 页面,展示 OAuth 登录按钮 |
| 25 | + status: completed |
| 26 | + - id: auth-callback-page |
| 27 | + content: 新建 /auth/callback 页面处理 OAuth 回调 |
| 28 | + status: completed |
| 29 | + - id: auth-service |
| 30 | + content: 新建 web services/auth.ts,封装 auth/me、oauth/status 等 API 调用 |
| 31 | + status: completed |
| 32 | + - id: layout-auth |
| 33 | + content: 修改 layout.tsx 鉴权逻辑,OAuth 开启时校验登录状态并支持重定向 |
| 34 | + status: completed |
| 35 | +isProject: false |
| 36 | +--- |
| 37 | + |
| 38 | +# OAuth2 登录插件配置方案 |
| 39 | + |
| 40 | +## 一、架构设计原则 |
| 41 | + |
| 42 | +- **协议优先**:采用标准 OAuth 2.0 / OpenID Connect 协议,不绑定任何特定系统 |
| 43 | +- **可插拔**:OAuth2 为可选开关,默认关闭时行为与当前完全一致 |
| 44 | +- **用户模块**:建立独立的用户与权限管理模块,登录可接入外部 OAuth2 协议 |
| 45 | +- **第一版范围**:仅实现用户登录鉴权,不与 LLM key、tool 鉴权关联 |
| 46 | + |
| 47 | +## 二、当前状态分析 |
| 48 | + |
| 49 | + |
| 50 | +| 模块 | 现状 | |
| 51 | +| ------ | ---------------------------------------------------------------------------------------------------------- | |
| 52 | +| 配置存储 | [derisk_core/config](packages/derisk-core/src/derisk_core/config/schema.py) 的 AppConfig,持久化到 `derisk.json` | |
| 53 | +| 配置 API | [config_api.py](packages/derisk-app/src/derisk_app/openapi/api_v1/config_api.py) 提供 `/api/v1/config/`* | |
| 54 | +| 设置页面 | [settings/config/page.tsx](web/src/app/settings/config/page.tsx) 含模型、Agent、沙箱、授权、工具等 Tab | |
| 55 | +| 登录逻辑 | [layout.tsx](web/src/app/layout.tsx) 中 `handleAuth` 为 MOCK,直接设置假用户到 localStorage | |
| 56 | +| 用户表 | `user` 表存在(id, name, fullname),可扩展用于 OAuth 用户 | |
| 57 | + |
| 58 | + |
| 59 | +## 三、配置结构设计 |
| 60 | + |
| 61 | +在 AppConfig 中新增 `oauth2` 字段(默认关闭): |
| 62 | + |
| 63 | +```python |
| 64 | +# OAuth2 配置结构 |
| 65 | +oauth2: |
| 66 | + enabled: false # 开关,默认 false |
| 67 | + providers: |
| 68 | + - id: "github" # 预设:github |
| 69 | + type: "github" # github | custom |
| 70 | + client_id: "" |
| 71 | + client_secret: "" |
| 72 | + # custom 类型额外需要: |
| 73 | + # authorization_url, token_url, userinfo_url, scope |
| 74 | +``` |
| 75 | + |
| 76 | +- **GitHub 预设**:固定使用 `https://github.com/login/oauth/authorize` 等标准端点 |
| 77 | +- **自定义**:支持任意 OAuth2 兼容服务器(authorization_url、token_url、userinfo_url) |
| 78 | + |
| 79 | +## 四、实现模块 |
| 80 | + |
| 81 | +### 4.1 后端 |
| 82 | + |
| 83 | +**1. 配置 Schema 扩展** |
| 84 | + |
| 85 | +- 文件:[packages/derisk-core/src/derisk_core/config/schema.py](packages/derisk-core/src/derisk_core/config/schema.py) |
| 86 | +- 新增 `OAuth2ProviderConfig`、`OAuth2Config`,在 `AppConfig` 中增加 `oauth2: Optional[OAuth2Config] = None` |
| 87 | + |
| 88 | +**2. OAuth2 认证 API** |
| 89 | + |
| 90 | +- 新建 `packages/derisk-app/src/derisk_app/openapi/api_v1/auth_api.py` |
| 91 | +- 路由: |
| 92 | + - `GET /api/v1/auth/oauth/login?provider=github`:生成 state,重定向到 OAuth 授权页 |
| 93 | + - `GET /api/v1/auth/oauth/callback`:处理回调,用 code 换 token,拉取用户信息 |
| 94 | + - `GET /api/v1/auth/me`:返回当前登录用户(校验 session/token) |
| 95 | + - `POST /api/v1/auth/logout`:登出 |
| 96 | + |
| 97 | +**3. 用户模块** |
| 98 | + |
| 99 | +- 扩展 `user` 表:`oauth_provider`、`oauth_id`、`email`、`avatar`(通过 DDL 升级) |
| 100 | +- 首次 OAuth 登录时创建/更新本地用户 |
| 101 | +- 新建 `packages/derisk-app/src/derisk_app/auth/`:OAuth 流程、session 管理、用户服务 |
| 102 | + |
| 103 | +**4. 配置 API 扩展** |
| 104 | + |
| 105 | +- 在 [config_api.py](packages/derisk-app/src/derisk_app/openapi/api_v1/config_api.py) 中支持读写 `oauth2` 配置 |
| 106 | +- 或通过现有 `import_config` 的 `extra` 机制透传(需保证 schema 校验) |
| 107 | + |
| 108 | +### 4.2 前端 |
| 109 | + |
| 110 | +**1. 设置页 OAuth2 配置卡片** |
| 111 | + |
| 112 | +- 文件:[web/src/app/settings/config/page.tsx](web/src/app/settings/config/page.tsx) |
| 113 | +- 在 `VisualConfig` 中新增 Card「OAuth2 登录配置」 |
| 114 | +- 内容:Switch(enabled)、Provider 列表(GitHub + 自定义)、表单(client_id、client_secret 等) |
| 115 | + |
| 116 | +**2. 登录页** |
| 117 | + |
| 118 | +- 新建 `web/src/app/login/page.tsx` |
| 119 | +- 根据配置展示「使用 GitHub 登录」「使用 XXX 登录」等按钮 |
| 120 | +- 点击后跳转到 `/api/v1/auth/oauth/login?provider=xxx` |
| 121 | + |
| 122 | +**3. 回调页** |
| 123 | + |
| 124 | +- 新建 `web/src/app/auth/callback/page.tsx` |
| 125 | +- 接收后端重定向,从 URL 获取 token/session 信息并写入 localStorage,再跳转到首页 |
| 126 | + |
| 127 | +**4. Layout 鉴权逻辑** |
| 128 | + |
| 129 | +- 文件:[web/src/app/layout.tsx](web/src/app/layout.tsx) |
| 130 | +- 调用 `GET /api/v1/auth/oauth/status` 或 `GET /api/v1/auth/me` 判断是否启用 OAuth 及是否已登录 |
| 131 | +- 当 OAuth 关闭:保持现有 MOCK 逻辑(或直接视为已登录) |
| 132 | +- 当 OAuth 开启且未登录:重定向到 `/login` |
| 133 | + |
| 134 | +## 五、数据流示意 |
| 135 | + |
| 136 | +```mermaid |
| 137 | +flowchart TB |
| 138 | + subgraph Config [配置层] |
| 139 | + A[settings/config] |
| 140 | + A --> B[oauth2.enabled=false] |
| 141 | + A --> C[oauth2.providers] |
| 142 | + end |
| 143 | +
|
| 144 | + subgraph AuthFlow [OAuth 开启时] |
| 145 | + D[用户访问] --> E{已登录?} |
| 146 | + E -->|否| F[重定向 /login] |
| 147 | + F --> G[点击 GitHub 登录] |
| 148 | + G --> H[/auth/oauth/login] |
| 149 | + H --> I[OAuth 授权页] |
| 150 | + I --> J[/auth/oauth/callback] |
| 151 | + J --> K[创建/更新用户] |
| 152 | + K --> L[写入 Session] |
| 153 | + L --> M[重定向首页] |
| 154 | + E -->|是| N[正常访问] |
| 155 | + end |
| 156 | +
|
| 157 | + subgraph Compat [OAuth 关闭时] |
| 158 | + O[用户访问] --> P[沿用现有逻辑] |
| 159 | + P --> Q[无登录校验] |
| 160 | + end |
| 161 | +
|
| 162 | + B -->|false| Compat |
| 163 | + B -->|true| AuthFlow |
| 164 | +``` |
| 165 | + |
| 166 | + |
| 167 | + |
| 168 | +## 六、关键文件清单 |
| 169 | + |
| 170 | + |
| 171 | +| 操作 | 文件路径 | |
| 172 | +| --- | ------------------------------------------------------------------------- | |
| 173 | +| 修改 | `packages/derisk-core/src/derisk_core/config/schema.py` | |
| 174 | +| 新建 | `packages/derisk-app/src/derisk_app/auth/`(oauth 流程、用户服务) | |
| 175 | +| 新建 | `packages/derisk-app/src/derisk_app/openapi/api_v1/auth_api.py` | |
| 176 | +| 修改 | `packages/derisk-app/src/derisk_app/openapi/api_v1/api_v1.py`(注册 auth 路由) | |
| 177 | +| 修改 | `web/src/app/settings/config/page.tsx` | |
| 178 | +| 新建 | `web/src/app/login/page.tsx` | |
| 179 | +| 新建 | `web/src/app/auth/callback/page.tsx` | |
| 180 | +| 修改 | `web/src/app/layout.tsx` | |
| 181 | +| 新建 | `web/src/services/auth.ts` | |
| 182 | +| 修改 | `assets/schema/`(user 表 DDL 升级) | |
| 183 | + |
| 184 | + |
| 185 | +## 七、向后兼容与安全 |
| 186 | + |
| 187 | +- **默认关闭**:`oauth2.enabled` 默认为 `false`,不改变现有行为 |
| 188 | +- **Session 安全**:使用 HttpOnly Cookie 或 JWT,避免 token 暴露在前端 |
| 189 | +- **State 防 CSRF**:OAuth 流程中校验 state 参数 |
| 190 | +- **Secret 存储**:client_secret 仅存于服务端配置,不暴露给前端 |
| 191 | + |
| 192 | +## 八、后续扩展(本版不做) |
| 193 | + |
| 194 | +- 与 LLM key、tool 鉴权的关联 |
| 195 | +- 权限/角色管理(RBAC) |
| 196 | +- 多 OAuth 提供商同时启用时的策略选择 |
| 197 | + |
0 commit comments