小米手机 Notion 密钥登录失败分析
# Notion App 通行密钥(Passkey)登录卡死排查分析报告
## 1. 现象描述
完成 `credential_service` 的底层配置并重启手机后:
* **Chrome 浏览器:** 访问通行密钥测试站(如 `passkeys.io`),能正常唤起系统底栏与指纹验证,秒级完成 Passkey 登录。
* **Notion App:** 点击“使用通行密钥登录”后,界面无任何系统弹窗,持续转圈,最终静默失败或提示超时。
---
## 2. 日志抓取与根因定位
通过终端监控实时日志:
`adb logcat -s CredentialManager Fido CredManController`
在 Notion 点击登录的瞬间,捕获到核心阻断日志:
> CredentialManager: starting executeGetCredential with callingPackage: notion.id
> ...
> CredentialManager: Remote provider responded with a valid response: ComponentInfo{com.google.android.gms/...RemoteService}
> CredentialManager: Remote entry being dropped as it is not from the service configured by the OEM.
> CredentialManager: Remote entry being dropped as it does not meet the restriction checks.
> ...
> CredentialManager: Client binder died - clearing session
### 根因深度剖析
1. **调用通道分化:**
* **Chrome(本地通道):** Chrome 拥有独立通道,直接与 Google Play 服务的本地 FIDO 认证组件(`PasswordAndPasskeyService` / `AuthenticationActivity`)通讯,完全避开了系统的跨进程 OEM 过滤器。
* **Notion App(标准远程通道):** Notion 按照 Android 标准的 `androidx.credentials` 规范向系统进程(`system_server`)请求凭据。系统判定其为外部跨设备请求,并唤起 GMS 的 `RemoteService`。
2. **小米 OEM 校验逻辑拦截:**
在向 Notion 返回数据之前,系统的 `CredentialManagerServiceImpl` 强制校验了服务来源是否属于编译时指定的 OEM 服务。因 GMS 远程凭据未通过该 OEM 校验,数据被系统底层**静默丢弃(Dropped)**。
3. **死锁与超时:**
数据被底层丢弃后,系统未向 Notion 抛出失败异常,Notion 无法捕获任何结果导致持续转圈,直至 Binder 会话超时强制断连(`Client binder died`)。
---
## 3. 测试与结论
### ADB 外部配置无效
后续尝试通过 ADB 写入 `credential_service_primary` 并调整 `device_config`(禁用 OEM 覆盖策略),日志证实拦截依然原样触发:
> W CredentialManager: Remote entry being dropped as it is not from the service configured by the OEM.
### 结论
该 OEM 限制并非独立 APK 软件行为,而是写死在系统核心框架(`services.jar` 内的 `CredentialManagerServiceImpl`)中,读取的是静态编译于 `framework-res.apk` 的白名单配置。**免 Root 状态下无法通过 ADB、卸载应用或修改系统属性来解除该限制**。
---
## 4. 应对与解决方案
### 方案 A:浏览器中转(免 Root 推荐)
1. 在手机端使用 **Chrome 浏览器** 打开 `www.notion.so`。
2. 在网页端完成通行密钥(Passkey)登录。
3. 登录后通过网页提示或页面设置点击 **“在应用中打开”**(Open in Notion App),无缝继承登录状态回客户端。
### 方案 B:传统凭据登录(免 Root)
在 Notion 登录界面选择使用常规密码或“邮箱临时登录码(Magic Link)”完成身份验证,绕过底层 Passkey 接口。
### 方案 C:框架层 Hook(需 Root)
在已解锁 BL 并配置 Magisk / KernelSU + LSPosed 的环境下:
* 借助针对小米系统的模块(如 Cemiuiler / 核心破解)。
* 动态 Hook `CredentialManagerServiceImpl` 中的 `isFromConfiguredServiceLocked` 方法,强行返回 `true`,彻底移除 OEM 远程丢弃限制。