v1xingyue/dsh-auth-plugin ↗★ 1
dsh-auth-plugin
DSH Web 用户授权插件 — 用户名密码 + 通用 OAuth 2.0(内置 GitHub/Google/Discord 等模板)+ Solana/EVM 钱包登录。零依赖核心,纯配置接入
安装
$
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:v1xingyue/dsh-auth-plugin说明文档
阅读完整 README ↗(默认 admin/admin123,启动警告,请立即覆盖配置)
安装后在 profile 的 `cordis.patch.yml` 按 id 覆盖 config 即可:
```yaml
- id: auth
config:
users:
admin: { password: "scrypt$...", role: admin }
oauth:
providers:
github: { builtin: github, clientId: "...", clientSecret: "..." }
已在隔离 DSH_HOME 完整验证:
dsh plugin add→ bundles 列表 自动追加 →--dump-config出现# == dsh-auth-plugin段。
安装后文件布局
~/.dsh/profiles/web/
├── cordis.patch.yml # 认证配置(insert auth 行)
├── dsh-auth-plugin.js # 插件本体(单文件)
├── package.json # profile manifest(可选加 "type": "module")
└── pnpm-workspace.yaml
快速开始
# cordis.patch.yml —— 最简配置:用户名密码登录
- insert:
- id: auth
name: "./dsh-auth-plugin.js"
config:
users:
admin: admin123
## 配置参考
### 顶层配置
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | boolean | `true` | 总开关 |
| `secret` | string | 每次启动随机 | 会话签名密钥;可用环境变量 `DSH_AUTH_SECRET` 固定 |
| `ttlHours` | number | `24` | 会话有效期(小时) |
| `title` | string | `DSH 登录` | 登录页标题 |
| `cookie` | string | `dsh_session` | 会话 Cookie 名 |
| `users` | dict | 空→`admin/admin123` | 用户表(见下) |
| `solana` | `false` \| object | `false` | Solana 钱包登录配置(见下) |
| `evm` | `false` \| object | `false` | EVM 钱包登录配置(见下) |
| `oauth` | object | `{providers:{}}` | 通用 OAuth 配置(见下) |
| `publicPaths` | string[] | 见下 | 免认证路径(精确或前缀匹配) |
默认 `publicPaths`:`/login`、`/api/auth/login`、`/api/auth/logout`、
`/favicon.ico`
> ⚠️ **`secret` 为空时每次启动随机**——重启后所有会话失效需重新登录。
> 这是保守设计(无需持久化);生产环境建议固定:`secret: !!js process.env.DSH_AUTH_SECRET`。
### `users` 三种写法
```yaml
### 顶层配置
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | boolean | `true` | 总开关 |
| `secret` | string | 每次启动随机 | 会话签名密钥;可用环境变量 `DSH_AUTH_SECRET` 固定 |
| `ttlHours` | number | `24` | 会话有效期(小时) |
| `title` | string | `DSH 登录` | 登录页标题 |
| `cookie` | string | `dsh_session` | 会话 Cookie 名 |
| `users` | dict | 空→`admin/admin123` | 用户表(见下) |
| `solana` | `false` \| object | `false` | Solana 钱包登录配置(见下) |
| `evm` | `false` \| object | `false` | EVM 钱包登录配置(见下) |
| `oauth` | object | `{providers:{}}` | 通用 OAuth 配置(见下) |
| `publicPaths` | string[] | 见下 | 免认证路径(精确或前缀匹配) |
默认 `publicPaths`:`/login`、`/api/auth/login`、`/api/auth/logout`、
`/favicon.ico`
> ⚠️ **`secret` 为空时每次启动随机**——重启后所有会话失效需重新登录。
> 这是保守设计(无需持久化);生产环境建议固定:`secret: !!js process.env.DSH_AUTH_SECRET`。
### `solana` 配置
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | boolean | `true`(对象形式) | 开关;`solana: false` 或省略 = 禁用 |
| `challengeTtlMs` | number | `300000` | nonce 有效期(5 分钟) |
| `allowlist` | string[] | **必填** | 公钥白名单(base58),至少 1 个 |
| `role` | string | `user` | 钱包登录默认角色 |
> ⚠️ **`allowlist` 必填**:启用时缺字段或空数组都会在加载时报配置错误
> (schema 层拦截)——**不允许"任何钱包可登录"**。
### `evm` 配置(MetaMask 等 EVM 钱包)
```yaml
evm:
enabled: true
allowlist: # 必填:只允许这些 0x 地址(小写或混合大小写均可)
- "0x4e984616e2dd9dffe7f2413efc7da35ef64c4117"
role: user
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | true(对象形式) | 开关;evm: false 或省略 = 禁用 |
challengeTtlMs | number | 300000 | nonce 有效期(5 分钟) |
allowlist | string[] | 必填 | 允许的 0x 地址,至少 1 个 |
role | string | user | 登录成功角色 |
⚠️ 同 Solana:
allowlist必填;且需要可选依赖@noble/curves+@noble/hashes(dsh plugin --profile web add @noble/curves @noble/hashes), 缺失时该功能自动禁用(其余登录不受影响)。
oauth 通用 OAuth 2.0 配置
每个 provider 一条,纯配置接入任意标准授权码 OAuth 服务。
支持内置模板:填 builtin + 凭据即可,端点/字段映射/scope 自动填充。
最简方式:内置模板(推荐)
oauth:
providers:
github: # provider id
builtin: "github" # ← 内置模板:端点/字段/scope 自动填充
clientId: "Ov23li..."
clientSecret: "ghp_..." # 仅服务端使用,绝不下发浏览器
内置模板一览(BUILTIN_OAUTH,显式字段可覆盖模板):
| builtin | 授权端点 | token 端点 | userinfo 端点 | 默认 scope | idField |
|---|---|---|---|---|---|
github | github.com/login/oauth/authorize | …/access_token | api.github.com/user | read:user | id |
google | accounts.google.com/o/oauth2/v2/auth | oauth2.googleapis.com/token | …/oauth2/v3/userinfo | openid email profile | sub |
discord | discord.com/oauth2/authorize | discord.com/api/oauth2/token | discord.com/api/users/@me | identify email | id |
gitlab | gitlab.com/oauth/authorize | gitlab.com/oauth/token | gitlab.com/api/v4/user | read_user | id |
microsoft | login.microsoftonline.com/common/oauth2/v2.0/authorize | …/token | graph.microsoft.com/v1.0/me | User.Read | id |
bitbucket | bitbucket.org/site/oauth2/authorize | …/access_token | api.bitbucket.org/2.0/user | account | uuid |
完整方式:显式配置(任意标准 OAuth 服务)
oauth:
providers:
custom:
label: "我的服务"
clientId: "..."
clientSecret: "..."
authorizeUrl: "https://.../authorize"
tokenUrl: "https://.../token"
userInfoUrl: "https://.../userinfo"
scope: "read" # 可选
idField: "id" # 可选,默认 id
nameField: "name" # 可选
emailField: "email" # 可选
role: "user" # 可选
# redirectUri: "https://..." # 可选:显式回调地址
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
builtin | string | "" | 内置模板名(见上表);填了则端点/字段/scope 用模板 |
label | string | provider id / 模板 | 登录页按钮文案 |
clientId / clientSecret | string | 必填 | OAuth 应用凭据 |
authorizeUrl / tokenUrl / userInfoUrl | string | 模板值 | 三个端点 |
responseType | string | code | 授权响应类型(授权码模式) |
scope | string | 模板值/空 | 请求的 scope(空格分隔) |
redirectUri | string | 自动 | 显式回调地址;留空 = http:///api/auth/oauth//callback |
idField / nameField / emailField | string | id / 模板 | userinfo 字段映射 |
emailDomains | string[] | [] | 邮箱域名白名单;非空时邮箱域名必须命中,否则拒绝(oauth_email_not_allowed) |
role | string | user | 登录成功角色 |
userInfoHeaders | dict | {} | 取 userinfo 附加请求头 |
tokenParams | dict | {} | token 请求附加参数 |
stateTtlMs | number | 600000 | state 有效期(10 分钟) |
回调地址(OAuth 应用后台填写):
http(s):///api/auth/oauth//callback例如:http://127.0.0.1:3080/api/auth/oauth/github/callback未知builtin名或合并后缺必需字段会在启动时报配置错误。