看图解,关注后续实测
小红书 Anaxagore:用多页卡片看懂指纹后卡住的原因。
真实设备排查 · Android / WebAuthn
小米14上,ChatGPT 登录的指纹已经通过,网页和 App 却停在原地。这篇记录从症状、日志、源码到恢复登录的证据,也说明哪些原因仍未证实。
internal 后,网页和 App 均恢复登录。我原本准备在手机上把 ChatGPT 订阅降到 Plus。第一步登录就卡住了:选择小米密码管理器里以前一直能用的通行密钥,指纹验证通过,然后没有任何反应。换到 Chrome 网页也是同样的现象。本文记录恢复登录;并不把订阅降级写成已经完成。
密钥是在这台手机上创建的。重启手机、重启相关组件、升级系统后仍失败,说明这些尝试没有解决本案。网页和 App 同时失败,提示它们可能共用出了问题的认证链路。
| 项目 | 本案记录 |
|---|---|
| 设备 | 小米14(23127PN0CC),Android 16 / SDK 36,中国大陆版 HyperOS |
| 系统 | OS3.0.306.0.WNCCNXM → OS3.0.307.0.WNCCNXM,升级后仍失败 |
| Chrome | 154.0.8037.126 |
| ChatGPT App | 1.2026.272 |
| 小米密码管理器 / FIDO | 1.0.18 / 220260320 |
| 恢复对照 | 仅将既有 allowCredentials 的 transports 限定为 internal;用户确认网页与 App 登录成功 |
记录显示 Chrome、ChatGPT 和 Google Play 服务在 10 月 9 日更新过,密码管理器在 8 月 21 日更新过。这些日期只是时间线,尚不能证明哪一次安装更新首次触发了故障。
已保存的脱敏异常摘录指向小米 FIDO 请求处理。它说明认证流程中发生了空指针,而不是证明指纹失败或密钥丢失。现场完整日志未存档,下面不冒充完整原始日志:
MiFido_fido2_CredentialRequest:
java.lang.NullPointerException:
Attempt to invoke virtual method java.lang.String d3.e.g()
on a null object reference
cr_ChromiumWebauthn:
CredMan getCredential call failed with
android.credentials.GetCredentialException.TYPE_UNKNOWN只读分析这台手机安装的 FIDO 组件后,发现其连接类型映射找不到枚举时会返回 null;调用方把结果放进列表,后续遍历却直接调用它的方法,没有跳过 null。这提供了能解释异常的方法级证据。
登录页面的候选凭据没有提供有效的 transports 列表。实际阅读手机精确 Chrome 版本的官方源码后,发现 Blink 会把缺省或空列表扩展为六种连接类型,包括 smart-card。请求经 Android CredMan 路径转换为 JSON。
这台设备的小米组件只识别五种对应类型,未识别的字符串会得到 null。由此形成目前最有证据支持的因果模型:
关键边界:没有直接捕获本案 Android 服务入口的原始 JSON,也没有升级前 Chrome 二进制对照,因此具体当次触发字符串仍是强证据支持的推断。另一个 Chromium 修补涉及传往 GmsCore 的 Parcel 路径,不能据此声称小米 CredMan JSON 路径已修好。
本案使用临时浏览器调试处理,在认证页面发起请求之前,把已有候选凭据的连接提示改成 internal,让请求只寻找本机平台认证器。这个提示在 WebAuthn 中用于定位认证器。
下面是处理逻辑的可读摘录,需要在自己的认证页面、请求发出前由调试工具执行。本案还通过临时观察器处理新开的 App 登录页;只粘贴这段代码并不保证覆盖页面跳转或 App 新窗口。
(() => {
if (location.hostname !== 'auth.openai.com' ||
window.__xiaomiTransportCompat) return;
const original = navigator.credentials.get.bind(navigator.credentials);
navigator.credentials.get = function(options) {
const pk = options?.publicKey;
if (pk?.rpId === 'openai.com' && pk.allowCredentials?.length) {
options = {...options, publicKey: {...pk,
allowCredentials: pk.allowCredentials.map(c =>
({...c, transports: ['internal']}))}};
}
return original(options);
};
window.__xiaomiTransportCompat = true;
})();处理保留了凭据 ID、challenge、RP 和用户验证要求,仍须指纹确认与服务器校验。同一份密钥随后在网页及 App 登录成功,所以实验支持请求兼容问题,而不是“必须重建密钥”。
这段处理只适用于本案的本机密钥;外置安全密钥和跨设备认证需要其他连接方式。刷新、新开认证窗口或下次登录可能失效。不要删除唯一可用密钥或把恢复密钥交给别人;临时恢复登录也不等于厂商组件已永久修复。
脱敏报告已发给小米官方开发者反馈邮箱;目前没有确认官方已受理或修复。我们希望通过其他设备的对照,把影响范围查清,而不是从单台成功推广成所有 Android 的结论。
如果你遇到同样现象,请在评论或已有技术讨论中提供:机型、系统版本、Chrome 版本、密钥管理器名称、指纹后具体表现、网页与 App 是否一致。不要提供邮箱、凭据 ID、密钥、恢复码或带认证参数的登录链接。
设备异常、安装包只读分析与恢复实验是本案直接证据;源码提供机制解释。六项语义模型检查并非手机二进制重放。本页不公开账户数据、密钥或原始 APK。
On a Xiaomi 14 running mainland HyperOS and Chrome 154.0.8037.126, fingerprint verification completed but ChatGPT passkey login stalled in both the website and Android app. Saved error excerpts show a null-pointer exception in Xiaomi's FIDO component.
Version-matched Chromium source and read-only device component analysis support a compatibility hypothesis: omitted transports expand to a list including smart-card, while the older provider may map an unknown transport to null and dereference it. The exact Android service payload was not captured.
A temporary wrapper restricted existing credential transport hints to internal, preserving credential IDs, challenge, RP and user verification. The user confirmed successful web and app login with the same passkey. This was tested on one setup; it is not a permanent provider fix or a universal Android workaround.
我整理的账号注册与订阅流程,方便按步骤核对准备事项。
我整理的代理订阅与客户端配置流程,按你的使用场景继续阅读。
这两篇是独立的上手指南。本案登录故障的证据指向通行密钥组件兼容问题,换订阅或购买代理不构成本案修复方法。
喜欢这种从真实故障查到源码的排查记录,可以在上方小红书图解关注 Anaxagore,或通过公众号文章关注作者;后续复现和官方修复进展会在有证据时补充。