# Cursor Passkey 登录：注册公钥凭据，验证挑战一次性与来源校验

原生WebAuthn与Python fido2完成注册、签名登录、重放拒绝和错origin拒绝；使用Chromium虚拟认证器，未碰个人Passkey。

## 环境

- Python 3.12+；在 reference 中 pip install -r requirements.txt。
- Node.js 24+；进入 reference 后 npm install。依赖为锁定的直接版本，首次安装需要网络。
- 可运行 node verify.mjs 自动创建临时虚拟认证器并验证四种响应；不使用个人凭据。
- 使用 http://localhost:8787，rpId为localhost。作者原生测试用Chromium CDP虚拟认证器，普通硬件流程须另验。

## 启动

~~~sh
cd reference
python3 server.py --port 8787
~~~

## 七步操作

1. 启用练习认证器

只创建 Chromium CDP 虚拟认证器，用户为 exercise@example.invalid，不触碰个人设备已有Passkey。服务器使用成熟 fido2 库，本机 origin 与 rpId 明确对应。

2. 注册真实凭据

浏览器调用 navigator.credentials.create 完成真实 WebAuthn 注册，服务器 register_complete 解析并保存公钥凭据。按钮变化不是注册成功的验收依据。

3. 请求新Challenge

每次登录重新 authenticate_begin，生成一次性challenge。浏览器从JSON解析请求参数，再通过 navigator.credentials.get 产生认证响应。

4. 验证签名登录

服务器 authenticate_complete 用保存的公钥、challenge和origin验证签名。正常登录真实返回200；下载结果记录的是本地软件认证器，不是硬件测试。

5. 拒绝重放响应

把已经成功使用的同一响应再提交一次，服务器因challenge状态已消费返回400。只比对credential ID而不消费challenge会遗漏这个问题。

6. 拒绝错误Origin

再生成一次新挑战，故意篡改响应clientData中的origin，验证服务器拒绝。修改JSON必须真的到达原生验证器，不能由前端自己显示“已拦截”。

7. 区分虚拟与硬件

阅读注册、登录、重放与错origin四种真实HTTP结果。虚拟认证器不证明生物识别、跨设备同步或手机硬件兼容；Cursor账号生成会话和生产登录系统未运行。

## 目录身份

- starter：待完成的任务接口与原创输入，TODO不是已完成实现。
- reference：作者原生完成参考和实际产物。records.json/browser-result.json为本地实测记录，不是AI助手回复。
- TASK.md：可交给相应AI助手的原始任务合同。该助手账号生成会话未运行。

## 依赖与许可

原创教学代码以MIT许可提供。第三方项目、模型及浏览器遵循其自身许可。第三方依赖由本地安装获取，不包含node_modules、模型权重、WASM运行时、数据库、缓存或凭据。

## 官方依据

- https://www.w3.org/TR/webauthn-3/
