feat: sign in with a passkey (WebAuthn, ES256, discoverable credentials) and manage your passkeys [CI]
This commit is contained in:
1 parent
ddb6608e32
commit
6385c1b9a3
31 files changed
+2296
-42
No files matched your search
+10
-1
@@ -70,6 +70,15 @@
|
||||
- 建议每个账户至少注册两个 passkey(手机加硬件密钥)。
|
||||
- **离线恢复密钥**:创建 owner 时同时生成一把离线的 ECDSA 恢复密钥,作为 `type=ecdsa`、`recovery=true` 的 owner 凭证写进操作员集合;私钥打印或放进密码管理器,平时不用。节点强制它**只能签操作员集合更新**,不能签委托、入网券和吊销表,所以即使被偷走,也加不了节点;它的用处是 passkey 全部丢失时签一版新的操作员集合、重新加 passkey,节点不用重装。
|
||||
|
||||
### 3.1 passkey 登录的实现(已完成)
|
||||
|
||||
- 流程:登录页「使用 Passkey 登录」→ `POST /api/admin/auth/passkey/options` 取挑战 → 浏览器 `navigator.credentials.get`(可发现凭证,不用输用户名)→ `POST /api/admin/auth/passkey/login` 提交断言 → 建立会话(Cookie,或跨域前端用 `return_session`)。注册:已登录用户在「系统 → 用户 → 我的 Passkey」添加,`POST /api/admin/auth/passkeys/options` 加 `POST /api/admin/auth/passkeys`;每个用户最多 10 个。
|
||||
- 校验:挑战在内存里,一次有效、5 分钟过期,并且区分注册和登录、绑定用户;`rpIdHash`、UP 和 UV 标志、`clientDataJSON` 的 type、challenge、origin、ES256 签名;签名计数器只增不减(两边都是 0 的同步型 passkey 不检查)。登录失败一律 401,不区分原因,和密码登录共用限流。
|
||||
- 验证断言的纯函数是 `Fleet.Identity.WebAuthnAssertion`(只用 BCL,节点以后验证 passkey 签出的委托也用它);注册里的 CBOR 和 attestation 解析在 Backend(`WebAuthnRegistration`),attestation 一律当 `none`,节点不带 CBOR。
|
||||
- 依赖方(RP):`MoShiro__WebAuthnRpId`(缺省取 `PublicUrl` 的主机,没有就取请求的主机)和 `MoShiro__WebAuthnOrigins`(缺省取 `PublicUrl` 的来源)。**passkey 绑定在这个域名上,改了会让已注册的 passkey 失效。**只有和后端同站的页面能用 passkey 登录,管理端在「添加其他后端」(跨域)时不显示这个入口。
|
||||
- 会话记录登录方式(`password` 或 `passkey`,`sessions.auth_method`),只有 passkey 登录的会话以后能提权;API key 不是用户,不能注册 passkey。
|
||||
- 测试:`SoftwarePasskey` 在测试里模拟认证器走完整的注册和登录,覆盖错误的挑战、来源、RP、签名、缺少 UV、挑战重放、计数器回退、只能管理自己的 passkey;管理端用 Chromium 的 WebAuthn 虚拟认证器验证过注册和登录。
|
||||
|
||||
## 4. 提权窗口(信任类能力各管各的)
|
||||
|
||||
| 窗口 | 覆盖 | 默认时长 | 行为 |
|
||||
@@ -273,7 +282,7 @@
|
||||
## 12. 实施顺序(每步可独立验证和推送)
|
||||
|
||||
1. **能力模型与守卫**:`Capability`、`Principal.Has`、端点声明、对账测试、API key 创建界面(预设、全选、能力子集校验)。不改节点。**已实现**(破坏性:旧令牌作废,数据库迁移 v11 重建 `api_tokens`)。登录会话在步骤 2 之前拥有全部能力(包括信任类),信任类的 passkey 要求从步骤 2 起强制。IP 白名单推迟:本部署经 Cloudflare、frp 和 Caddy,后端看到的来源地址是代理,需要先有「可信代理」配置,才做得对。`events.read` 对应现有的 `GET /api/admin/events`,不是预留。
|
||||
2. **账户、passkey、会话分级、审计**:WebAuthn 注册与登录、提权窗口(接入、吊销、凭证三类)、审计日志、归属列和详情页显示。
|
||||
2. **账户、passkey、会话分级、审计**:WebAuthn 注册与登录、提权窗口(接入、吊销、凭证三类)、审计日志、归属列和详情页显示。**passkey 登录已实现**(见第 3.1 节);提权窗口、审计日志、归属列还没做。
|
||||
3. **操作员集合与创世公钥固定**:`fleet-enroll` 和安装命令改造、弱信任开关、离线恢复密钥的创建与导出。
|
||||
4. **入网链**:Grant、Ticket(含属主 `controllers`)、Binding 的签发和节点验证(验证一次、缓存结果);成员条目随期望状态下发、节点在状态同步时验证;Probe 只拨公网地址;`enroll` key;节点信任状态上报和管理页显示(第 14 节)。添加节点的界面可以选属主(默认添加者的全部 passkey)。
|
||||
5. **吊销表与操作员集合更新**;自动化夹具(测试里的软件 ECDSA 凭证);**安装脚本的供应链**(第 15 节:静态签名脚本、按 digest 拉镜像)。
|
||||
|
||||
Reference in new issue
Block a user