OAuth 2
作者: 王新栋
PKCE 协议,全称是 Proof Key for Code Exchange by OAuth Public Clients。
下面看一下PKCE 协议的交互流程
注意,为了突出第三方软件使用 PKCE 协议时与授权服务之间的通信过程,省略了受保护资源服务和资源拥有者的角色:
首先,App 自己要生成一个随机的、长度在 43~128 字符之间的、参数为 code_verifier 的字符串验证码;接着,我们再利用这个 code_verifier,来生成一个被称为”挑战码”的参数code_challenge。
那怎么生成这个 code_challenge
的值呢?OAuth 2.0 规范里面给出了两种方法,就是看code_challenge_method
这个参数的值:
- 一种
code_challenge_method=plain
,此时code_verifier
的值就是code_challenge
的值; - 另外一种
code_challenge_method=S256
,就是将code_verifier
值进行 ASCII 编码之后再进行哈希,然后再将哈希之后的值进行 BASE64-URL 编码,如下代码所示:
1 | code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) |
那么如何使用呢?
在第一步获取授权码 code
的时候,我们使用 code_challenge
参数。需要注意的是,我们要同时将 code_challenge_method
参数也传过去,目的是让授权服务知道生成code_challenge
值的方法是 plain
还是 S256
。
1 | https://authorization-server.com/auth? |
在第二步获取访问令牌的时候,我们使用 code_verifier
参数,授权服务此时会将code_verifier
的值进行一次运算。那怎么运算呢?就是上面code_challenge_method=S256
的这种方式。
没错,第一步请求授权码的时候,已经告诉授权服务生成 code_challenge
的方法了。所以,在第二步的过程中,授权服务将运算的值跟第一步接收到的值做比较,如果相同就颁发访问令牌。
1 | POST https://api.authorization-server.com/token? |
现在,你就知道了我们是如何使用 code_verifier
和 code_challenge
这两个参数的了吧。
总结一下就是,换取授权码 code
的时候,我们使用 code_challenge
参数值;换取访问令牌的时候,我们使用 code_verifier
参数值。
由于网络不法分子这样的中间人虽然可以截获 code_challenge,但是他并不能由 code_challenge 逆推 code_verifier,只有客户端自己才知道这两个值。因此即使中间人截获了 code_challenge,Authorization Code 等,也无法换取Access Token,避免了安全问题。