Android端PKCE流程中如何安全存储state与code verifier
Android PKCE 授权流程临时参数存储方案
你碰到的进程被系统回收导致参数丢失是Chrome Custom Tab授权场景下的共性问题,仅存在内存里的code_verifier、state在应用切后台后完全不可靠,系统根据内存资源情况随时可能杀掉你的进程,没有任何办法100%阻止系统回收。
最佳存储实践
- 生成
code_verifier、code_challenge、state三个参数后,第一时间写入加密本地存储,不要等跳转Custom Tab之后再存。 - 存储选型优先用
EncryptedSharedPreferences,密钥由Android Keystore系统托管,不需要你自己硬编码密钥在代码里,能避免被逆向或者root环境下明文泄露。 - 存储的参数在完成JWT换取流程后必须立刻删除,不要长期残留在本地。如果存在多并发授权请求的场景,可以给每组参数绑定一个短随机请求ID做key,避免不同请求的参数混淆。
- 做异常兜底:如果收到授权回调时,本地找不到对应的
code_verifier和state,直接终止当前授权流程,重新发起一轮新的PKCE请求即可,绝对不能跳过state校验或者随便填verifier去换token,避免引入授权码劫持、CSRF类的安全风险。 - 不要依赖
onSaveInstanceState机制存这两个参数,不同厂商ROM对实例状态的持久化逻辑差异很大,应用进程完全被杀的场景下,这个方法存的值大概率会丢失,可靠性达不到要求。
本地存储的安全性说明
用上述加密方案存储到应用私有目录是安全的,完全符合原生应用OAuth2.0授权的安全规范,不存在本质风险:
- 这两个参数都是一次性短生命周期凭据,有效期只覆盖从发起授权到换取JWT的短短几分钟窗口,换取JWT成功后参数立刻失效,就算极端场景下被泄露,攻击者也没法利用过期的参数完成授权流程。
- 绝对不要把这两个参数存到外部公共存储目录,这类目录下的文件其他应用可随意读取,会直接引入泄露风险。普通明文SharedPreferences也不推荐,root环境下可被直接读取,存在安全隐患。
额外提醒:不要为了规避参数丢失的问题去掉state校验、或者用固定值生成code_verifier,这两种做法会直接废掉PKCE和state的安全防护能力,属于典型的为了体验牺牲安全的错误实现。
内容的提问来源于stack exchange,提问作者Preslav Petkov
相关产品推荐
相关产品推荐

