0%

OAuth 2 PKCE

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
2
3
4
5
6
https://authorization-server.com/auth?
response_type=code&
app_id=APP_ID&
redirect_uri=REDIRECT_URI&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256

第二步获取访问令牌的时候,我们使用 code_verifier 参数,授权服务此时会将code_verifier 的值进行一次运算。那怎么运算呢?就是上面code_challenge_method=S256 的这种方式。

没错,第一步请求授权码的时候,已经告诉授权服务生成 code_challenge 的方法了。所以,在第二步的过程中,授权服务将运算的值跟第一步接收到的值做比较,如果相同就颁发访问令牌。

1
2
3
4
5
6
POST https://api.authorization-server.com/token?
grant_type=authorization_code&
code=AUTH_CODE_HERE&
redirect_uri=REDIRECT_URI&
app_id=APP_ID&
code_verifier=CODE_VERIFIER

现在,你就知道了我们是如何使用 code_verifiercode_challenge 这两个参数的了吧。

总结一下就是,换取授权码 code 的时候,我们使用 code_challenge 参数值;换取访问令牌的时候,我们使用 code_verifier 参数值。

由于网络不法分子这样的中间人虽然可以截获 code_challenge,但是他并不能由 code_challenge 逆推 code_verifier,只有客户端自己才知道这两个值。因此即使中间人截获了 code_challenge,Authorization Code 等,也无法换取Access Token,避免了安全问题。

如何在移动App中使用OAuth2

欢迎关注我的其它发布渠道