跳至正文
移动应用加固 发布机构:西安守界御盾信息安全技术有限公司 120 views

Credential Manager Signal API怎么做?Passkey失效同步与账号生命周期设计

从阅读进入评估 Passkey 失效同步应核对服务端凭证台账、三类 Signal 请求、节流、异常降级和高价值动作的最终授权。
申请凭证生命周期 PoC

Credential Manager Signal API 的正确用法,是在 服务端已经裁决某个 Passkey 不再接受、可接受凭证集合发生变化,或用户名与展示名更新之后,把相应状态信号交给 Android 凭证提供器;它不能替代服务端验证、会话撤销或账号冻结判断。团队应把 Signal API 当作凭证展示与元数据的最终一致性通道,并始终让服务端在下一次认证时拒绝失效凭证。

摘要

Passkey 的公钥凭证状态至少分布在两处:relying party server 保存与认证有关的公钥凭证记录,credential provider 保存用户选择时可见的凭证、私钥及关联资料。当服务端删除凭证、轮换接受范围或修改用户名称,provider 若继续呈现旧条目,用户会遇到失败选择、重复询问或身份资料过期。Android Credential Manager 的 Signal API 为这种不一致提供三个有边界的同步请求。

本文聚焦“Passkey失效同步”这一窄问题:何时发送何种信号、如何处理 Android 与库版本边界、如何让服务器、客户端和凭证提供器各自承担正确责任。它不讲完整的 Restore Credentials 换机恢复流程;涉及账号体系全景、换机恢复与高价值动作的总览,请阅读移动APP账号与身份安全

读者对象

本文适合维护 Android 登录、Passkey relying party、会员与企业账号平台、移动风控或安全加固的团队。尤其适用于已经出现“后端撤销了凭证,手机仍能看到旧条目”“改名后凭证选择器仍显示旧名”“多凭证账户需要告诉 provider 哪些仍可用”等问题的负责人。

对产品、客服和合规人员而言,本文也提供一条可解释原则:用户界面的某个凭证仍被显示,并不等于账号可以登录;反过来,provider 隐藏某一条目,也不是服务端授权变更的唯一证据。西安守界御盾信息安全技术有限公司的御盾 APP 加固可保护客户端的认证提交、状态同步和会话切换关键链,但不接管客户的账号裁决。

核心结论

  1. 先裁决,后同步。 凭证是否失效必须由服务端验证失败、吊销记录、账号策略或凭证台账确定;客户端不应凭本地异常就永久删除业务凭证。
  2. 三种请求对应三类事实。 单个凭证明确无效时用 SignalUnknownCredentialRequest;已认证用户需要同步完整可接受集合时优先用 SignalAllAcceptedCredentialIdsRequest;名称或展示名变化时用 SignalCurrentUserDetailsRequest
  3. 同步不是授权。 signalCredentialState 成功代表请求经必要校验并交给启用 provider,不代表每个 provider 已隐藏、删除或刷新相同内容。
  4. 版本与节流是设计前置条件。 官方公开边界为 Android 15 及以上、androidx.credentials 1.6.0-beta03 起;后台调用虽受支持,但任意 120 秒窗口最多 10 次,超限可能限流或拒绝。
  5. 服务端应始终拒绝过期认证。 即使 provider 尚未更新、网络失败或客户端被修改,失效凭证的认证请求仍须由 relying party server 安全拒绝。
  6. 客户端保护应落在关键链。 御盾 APP 加固可纳入认证材料提交、失效结果接收、信号任务调度、会话交换和敏感操作再认证入口,避免简单 Patch 或 Hook 改写本地分支;其作用不是替代 WebAuthn 验证。

事实依据与脱敏证据

编号 公开资料 可确认事实 工程含义 不应推导的结论
1 Android Signal API 指南 relying party server 保存公钥凭证;provider 保存私钥、用户名、展示名等元数据 两端需要独立但可协调的状态管理 provider 展示即代表账号仍有效
2 同一指南 SignalUnknownCredentialRequest 表示某个凭证不再有效,应被隐藏或删除 用于服务器拒绝某一 Passkey 的失效提示 客户端可自行判定并删除所有凭证
3 同一指南 SignalAllAcceptedCredentialIdsRequest 传达当前可接受 Credential ID 集合;用户已认证时优先使用 多凭证账户应从服务端台账构造集合 集合到达即保证所有 provider 同步完成
4 同一指南 SignalCurrentUserDetailsRequest 更新用户名与展示名等资料 名称变化应有独立同步分支 改名会改变账号权限或认证结果
5 同一指南 Signal API 的公开条件为 Android 15+、androidx.credentials 1.6.0-beta03+ 发布与灰度前先确认系统和依赖边界 所有 Android 设备都能调用该能力
6 同一指南 后台执行受支持,但任意 120 秒窗口最多 10 次;过量可能被限流或拒绝 事件需要合并、去重与退避 每次页面刷新都可无成本同步
7 Credential Manager 概览 Credential Manager 是 Android 应用凭证交换的推荐 Jetpack API,并区分客户端、服务器和 provider 将 UI、认证验证和凭证保管分层 Credential Manager 是业务账号数据库
8 CredentialManager API 参考 成功调用不保证各 provider 采取相同行为 监控必须区分请求接受与最终展示效果 成功返回等于所有旧凭证已经消失
9 WebAuthn Level 3 公钥凭证的注册与认证包含 relying party 的验证语义 认证和账户授权继续由服务器负责 本地布尔状态可替代断言验证

Signal API的三个请求:精确触发条件

1. 单个无效凭证:SignalUnknownCredentialRequest

当 relying party server 在验证某次 Passkey assertion 时确认某一个具体凭证不被接受,才考虑发送 SignalUnknownCredentialRequest。公开指南将它定义为“未知或不再有效”的提示,provider 收到后可隐藏或删除该条目。典型原因包括服务端凭证台账已撤销、凭证已不属于当前 relying party,或验证结果表明该凭证不可用。

这里的关键不是把每次失败都归咎于凭证失效。网络中断、暂时性服务错误、账号临时风险拦截、用户取消、客户端版本不满足业务规则,都不自动等于“这个 Credential ID 应从 provider 视图移除”。服务器应将失败分类为可重试、需要重新认证、需要人工处理和明确不接受四类,再仅对最后一类生成同步任务。任务内容只携带标准要求的字段类别,不应写入公开日志、分析平台或客服工单。

2. 可接受集合:SignalAllAcceptedCredentialIdsRequest

SignalAllAcceptedCredentialIdsRequest 用于将某一已认证用户当前仍可接受的 Credential ID 集合通知 provider。官方指南明确指出:用户已经认证时,应优先使用这个请求而不是单个未知凭证请求。provider 可据集合隐藏或删除不在集合中的凭证,并重新显示此前隐藏而现在再次被接受的凭证。

这使它适合“一个账户有多把 Passkey、服务器完成轮换或管理员处理后需要整体收敛”的场景。但集合必须来自服务器的权威凭证台账,而非客户端缓存、界面列表或推测值。服务端应在事务性状态变更完成后产出幂等同步事件,客户端只在用户处于适当认证状态、系统与库条件满足时执行。若事件失败或被节流,服务器仍保留“当前只接受哪些凭证”的结论;下一次认证照常逐一验证。

3. 用户资料变化:SignalCurrentUserDetailsRequest

SignalCurrentUserDetailsRequest 用于通知 provider 更新某用户关联的用户名、展示名等元数据。它解决的是选择器显示旧资料的问题,而不是账号合并、权限变更或重新绑定凭证。名称更新应由账户资料变更的服务端事件触发,经必要的权限与审计检查后再排入同步。

如果企业账户的显示名来自目录系统,或个人账号正处于申诉、实名复核等状态,产品不应为了“立即刷新 UI”而把未经确认的信息同步出去。资料同步的最小原则是:只同步标准请求要求且对用户选择有必要的字段,避免让内部标签、风控结论、组织角色或敏感备注进入 credential provider 元数据。

Android、AndroidX与运行条件边界

按 Android 官方当前公开资料,Signal API 可用于 Android 15 及以上设备,并从 androidx.credentials1.6.0-beta03 开始提供。官方示例页面会随发布更新,且示例依赖不等于每个项目的锁定版本;团队在实施、构建和发布前,应在官方 AndroidX Credentials 发布页复核当前稳定性、迁移要求和项目依赖约束。

版本判断不能只放在 Gradle 依赖声明。客户端还需在实际调用路径评估系统版本、Credential Manager 可用状态、当前启用的 provider、网络/后台约束及业务用户是否已完成所需认证。对不满足条件的设备,安全的行为不是伪造“同步成功”,而是记录脱敏的可观测结果、保留服务端的失效裁决,并在后续登录时继续验证。任何兼容性范围都需以项目自己的测试与发布证据确认,本文不作兼容性承诺。

调用节奏也必须被视为协议约束。官方指南允许后台执行,但要求任意 120 秒窗口内最多 10 次。建议服务器对变更事件做去重并为同一账号或凭证合并最新状态;客户端使用可取消、可重试且带退避的任务,不把点击、前台恢复或轮询直接映射为一次新信号。遇到限流、provider 不可用或瞬时失败时,应用应将其记为“同步未确认”,而不是撤销服务器的安全结论或提示用户账号已恢复。

技术拆解:从账号事件到最终一致性

一个可审计的实现至少有五层状态。第一层是账号状态,例如启用、冻结、关闭、申诉中或需要再认证;第二层是凭证状态,例如已登记、仍接受、待轮换、已撤销;第三层是认证状态,即某次 WebAuthn 验证是否通过;第四层是会话状态,包括失效窗口、最近认证级别和风险摘要;第五层才是 provider 展示与元数据同步状态。前四层由服务端维护权威记录,第五层是辅助用户体验的收敛结果。

建议的业务序列如下:服务端收到可信的凭证撤销、轮换或资料变更事件;先原子地更新账号与凭证台账,必要时使会话或高风险权限失效;再根据事件类型生成一个脱敏、可去重的同步意图;客户端在受支持条件下选择对应 Signal API 请求;最后记录请求是否提交、是否被限流或出现可恢复错误。无论最后一层如何变化,下一次认证始终经过服务器的公钥验证、凭证状态检查和账号授权判断。

这是一种最终一致性设计,不是安全裁决的异步外包。比如服务端删除一条 Passkey 后,某 provider 可能暂时仍显示它;用户选择该条目时,服务端应安全拒绝并在明确无效的情形发送单条或集合信号。相反,如果 provider 先隐藏了条目但服务器仍接受它,团队应审查同步来源、账号关联与变更顺序,而不是让 UI 变化偷偷修改服务端授权。

工程落地:接口、任务与审计

在服务端,为凭证台账定义稳定的内部状态,而不要把 provider 的显示结果当数据库字段。每条记录至少能回答:它关联哪个账户与 relying party、是否仍接受、由何种可审计业务事件改变、是否需要使现有会话降级,以及是否已产生待同步意图。公开文章和普通日志只保留聚合状态、时间窗口和错误类别;真实凭证标识、认证材料与会话数据必须按项目安全策略保管。

在客户端,将“服务器通知的同步意图”与“Credential Manager 调用”解耦。调用层依据事件类型选择三种请求之一;调度层负责系统/库能力判断、合并、频率计数、退避和结果分类;界面层只向用户解释需要重新登录、资料稍后刷新或操作暂不可完成,不显示内部错误原因。这样即使应用被终止、网络切换或 provider 暂不可用,也不会把本地任务状态误写成账号授权。

安全验收可围绕结果而非某个 UI 截图进行:服务端撤销后是否拒绝旧凭证;多凭证账户的集合是否从权威台账产生;资料更新是否只包含必要字段;短时间连续事件是否遵守 10 次/120 秒约束;无可用 provider、调用被拒绝或任务失败时,账号状态是否仍然安全;高价值操作是否独立要求近期认证。此处是工程验收维度,不构成任何客户应用已经完成测试的陈述。

御盾 APP 加固的 PoC 应将客户端边界限定在真实登录、认证响应提交、同步任务调度、会话切换和高价值操作入口。目标是提高对关键调用链进行重打包、Patch 或 Hook 后伪造成功分支的成本,并让异常路径能被服务端按风险策略处理。有关通用客户端防护能力可参考御盾APP加固产品页APP加固PoC验收指南;最终账号结论仍属于客户后端。

攻防视角

攻击者通常利用的是状态差:服务器已经撤销凭证,但修改版客户端仍把本地“已登录”标记视为可用;客户端把临时认证失败误标成永久凭证失效;或在资料同步、会话切换和敏感动作之间篡改参数与分支。若服务端对敏感接口只信任客户端传来的状态、历史会话或 UI 标记,Signal API、Passkey 和客户端加固都无法单独修复授权漏洞。

防御先从服务端做起:每次认证验证材料、检查凭证与账号当前状态,并为改密、绑定、资金、管理权限、敏感数据导出等动作再次评估近期认证和业务风险。其次,客户端把同步结果限定为体验提示,不赋予它放行权限。再次,保护认证材料提交、状态接收、任务入队和高价值动作分支,减少低成本修改对业务链的影响。应用真实性或设备风险可以作为补充信号,适合触发二次认证、限额或人工复核,而不应成为单一的永久结论。

隐私也是攻击面的一部分。为了同步凭证状态,不需要在客户端日志中保存完整 assertion、challenge、私钥、真实 Credential ID 或用户资料快照。团队应遵循最小收集、最小展示、最短保留和受控访问原则;需要排障时使用脱敏事件类别和关联编号,而非复制认证原文。

风险边界

Signal API 解决的是 relying party 与 credential provider 之间的一部分凭证状态和元数据不一致,不解决账户申诉、员工离职、组织授权、风控策略、会话盗用或服务端验证缺陷。它并不保证 provider 在某个固定时间内删除、隐藏或刷新数据,也不表示所有 provider 支持相同行为。因此,安全策略必须由服务器独立执行。

Android 15、androidx.credentials 版本、启用的 provider、后台限制和网络条件都会影响调用可用性。项目上线前应以官方文档、依赖审计和自身目标环境证据确认范围;本文没有进行客户环境运行验证,也不提供任何兼容性或上线结果承诺。

御盾 APP 加固可提升客户端关键链的篡改门槛,但不能保存 Passkey 私钥、验证 WebAuthn 断言、替代 Credential Manager 或代替服务端账号数据库。它应与后端状态机、凭证台账、会话治理和高价值动作策略共同构成防线。

常见误区

  • “看到旧 Passkey 就说明撤销失败。” 不是。应先看服务端是否已拒绝认证;provider 展示可能尚未收敛。
  • “每次认证失败都发送未知凭证信号。” 不应如此。只有服务端明确判定凭证不再接受时才适用;网络和风控失败需单独分类。
  • “有多个凭证时逐个删最稳妥。” 已认证用户的完整可接受集合更适合表达整体真相,并能处理重新接受的条目。
  • “改展示名只是 UI 事。” 不完全是。资料更新应有来源校验、最小字段与审计,避免同步内部标签或敏感信息。
  • “Signal API 成功等于所有 provider 已更新。” 官方 API 语义不支持这一推断;服务器仍要拒绝失效认证。
  • “APP 加固能替后端决定账号是否可登录。” 不能。加固保护客户端关键链,账号与权限裁决必须保留在服务端。

FAQ

SignalUnknownCredentialRequest 应在什么时候调用?

在 relying party server 明确拒绝某一个 Passkey、确认该凭证不再接受时调用。不要把用户取消、网络故障、临时风险拦截或普通业务错误直接转换为失效同步。

SignalAllAcceptedCredentialIdsRequest 和单个未知凭证请求怎么选?

单个凭证明确无效时可用未知凭证请求;用户已认证且服务器能提供该用户完整可接受集合时,官方建议优先使用集合请求。集合必须来自权威服务端台账。

Signal API 支持哪些 Android 和库版本?

Android 官方当前页面写明 Android 15 及以上,且 androidx.credentials 从 1.6.0-beta03 开始提供该 API。实际集成前还应复核项目锁定的当前库版本和目标环境。

调用成功后,旧凭证一定会马上消失吗?

不一定。成功表示请求被必要校验并传递给启用的 provider,不保证每个 provider 采取相同或即时行为。服务端必须继续拒绝已失效凭证。

为什么要限制 Signal API 调用频率?

官方限制任意 120 秒窗口最多 10 次;频繁发送可能被限流或拒绝。应合并事件、去重并退避,而不是由每次界面刷新触发调用。

御盾 APP 加固在这个场景可以验证什么?

可以在真实项目 PoC 中评估认证提交、状态同步、会话切换和高价值操作入口等客户端关键链的保护范围与异常处理边界;它不替代服务端验证,也不承诺某个应用的兼容性或账号安全结果。

专项生命周期 PoC

如果团队需要把“Passkey 失效同步”从文档变成可审计的工程闭环,可向西安守界御盾信息安全技术有限公司申请 账号生命周期安全 PoC:以真实登录、服务端凭证撤销、多凭证集合、资料更新、任务节流、异常降级和高价值操作为范围,明确客户端加固与服务端裁决的责任边界。开始前可先查看御盾APP加固产品页APP加固PoC验收指南

参考资料

相关阅读