跳到主内容
快讯直播
AI智模界
AI 词典

OAuth PKCE:公共客户端为什么守不住密钥

一句话定义

OAuth PKCE(Proof Key for Code Exchange,读作 "pixy",直译"用于换取授权码的证明密钥")是 OAuth 2.0 授权码流程上的一层加固:客户端在发起登录时先提交一个由随机数算出的"挑战值",换令牌时再交出原始随机数,让偷到授权码的人换不出令牌。

它要补的漏洞

OAuth 2.0 授权码流程(Authorization Code Flow)大致是:用户被跳转到授权服务器登录并同意,服务器把浏览器重定向回客户端,带上一串 authorization code;客户端再拿这串码去换 access token(真正能调接口的凭证)。

问题出在"客户端是谁"这件事上。后端 Web 应用有服务器,可以把 client_secret 藏得很好;但手机 App、桌面软件、浏览器里的单页应用(SPA)属于公开客户端(public client),代码和配置就在用户设备上,secret 能被反编译或抓包扒出来——等于把钥匙和锁一起给了用户。

更糟的是,就算不要 secret,授权码本身也可能被截胡。手机上一个自定义回调地址(比如 myapp://callback)常常能被多个 App 注册,恶意 App 可以抢先接住重定向,拿到那串 code,再冒充你的客户端去换 token。

打个比方

像商场存包处:你存包拿到一张号码牌(code),取包时递上号码牌就行。号码牌被别人看到,包就归别人了。PKCE 的做法是——存包时你先想一句只有你知道的口令,只把口令的"指纹"告诉柜台;取包时除了号码牌,还得报出原句口令,柜台现算一遍指纹核对。

三步走

1. 客户端每次授权前生成一个随机字符串 code_verifier。

2. 算它的哈希:code_challenge = BASE64URL(SHA256(code_verifier)),随授权请求一起发给服务器(标记方法为 S256)。

3. 拿 code 换 token 时,把原始 code_verifier 一并提交。服务器重算哈希,对不上就拒绝。

关键在于:verifier 从头到尾没经过浏览器重定向,只待在发起登录的那个进程内存里,用完即扔。

它防住了谁

  • 同设备上抢到回调、截获 code 的恶意 App——没有 verifier,哈希对不上。
  • 从重定向 URL 里偷看 code 的中间人(浏览器其他页面、日志、Referer 泄露)。
  • 把别人的 code 硬塞给你客户端的注入类攻击——同样卡在 verifier 上。
对比项client_secretPKCE 的 code_verifier
存放位置客户端配置里,长期不变每次登录临时生成,仅在内存
公开客户端能否保密不能,可被逆向提取可以,从不下发、不落地
防授权码拦截基本无能为力有效
谁该用有后端可保密的机密客户端所有客户端;公开客户端必须

对从业者的意义

接第三方登录(GitHub、Google 等),或给 AI 应用做 MCP(Model Context Protocol)远程服务器的授权时,SDK 里那个 code_verifier / code_challenge 参数就是它,默认打开即可,别手写成固定值。OAuth 2.1 的草案已把 PKCE 从"公开客户端必需"扩大为对所有客户端的要求,具体条款以官方规范页面为准。它不替代 HTTPS,也不替代 token 的过期与撤销策略——只是一块很关键的拼图。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。