每次请求建立自己的验证值

客户端为每次授权请求生成高熵随机code_verifier,再由它导出code_challenge。验证值在后续交换中使用,挑战先随授权请求发送;这种先后分工使只有拿到授权码的一方未必能完成令牌交换。

S256方法先对验证值的ASCII表示作SHA-256,再用无填充base64url表示摘要。挑战是这个计算结果,不是把验证值换个字段名原样公开;RFC 7636要求有能力采用S256的客户端使用它,当前安全实践也强调不暴露验证值的挑战方法。

参考:[1] [2]

服务器把挑战与发出的授权码绑定

授权服务器发出授权码时,保存或可靠关联挑战及其计算方法。客户端到令牌端点提交授权码和code_verifier后,服务器按原方法重新计算并比较;不匹配时拒绝,而不是因为此前浏览器已点过同意便略过检查。

RFC 9700还要求防止降级:带验证值的令牌请求,必须对应先前确有挑战的授权请求。否则,单在交换步骤添加一个字段,却没有对照对象,无法证明这两步属于同一次被正确发起的事务。

参考:[1] [2]

不是统一客户端秘密或完整登录方案

PKCE最初针对公开客户端,但当前规范的建议也涵盖机密客户端。它的验证值是事务专用材料,不是给同一软件全部安装版本共用的一份永久客户端秘密;恒定挑战也无法提供所需的逐事务关联。

在服务器确实支持并正确绑定PKCE等条件下,它还可保护授权回调免受相应CSRF攻击。仍须验证重定向、令牌及其他协议条件,不能把启用PKCE解释为整个应用不再需要权限检查,或所有状态数据都自动防篡改。

参考:[2]