OAuth2放弃 Implicit Flow 使用Authorization Code+ PKCE完成授权认证

5/29/2025 10:01:40 AM
12
0

 Implicit Flow Password Grant,均已被标记为Legacy,且OAuth2.1里面已经删除了,目前OAuth2.1只剩三种flow:

  • Authorization CodePKCE
  • Client Credentials
  • Device Code

OAuth 2.0 在 RFC7636 中定义了一种扩展模式,这种模式下,客户端 不需要使用 client_secret,模式中 PKCE 的全称是 Proof Key for Code Exchange。那怎么理解这个呢?简单来说,就是我们仍然 使用 Authorization Code 模式的流程,但是原来是需要服务端参与保存 client_secret,现在改成客户端临时生成一对密钥。

步骤:

  1. 用户点击登录按钮
  2. 应用生成 code_verifier,是一个随机值,然后对 code_verifier 做sha256,得到哈希值 code_challenge
  3. 应用携带 client_idcode_challenge 请求 Authorization Server
  4. Authorization Server 提示用户是否授权
  5. 用户点击同意授权
  6. Authorization Server 生成 code,同时保存 code_challenge
  7. 应用使用 code 和 code_verifier 请求 Authorization Server
  8. Authorization Server 对 code_verifier 做sha256,得到哈希值,与 code_challenge 对比
  9. 对比成功,下发 access_token
  10. 应用请求资源
  11. access_token 校验通过,返回响应

部分伪代码片段

(1)用户重定向到授权服务器

GET https://auth.example.com/authorize?
  response_type=code&
  client_id=your-client-id&
  redirect_uri=https://yourapp.com/callback&
  scope=openid profile email&
  state=xyz123&
  code_challenge=abc123...&
  code_challenge_method=S256

注意:code_challenge_method=S256 表示使用 SHA256 哈希。

(2)客户端使用 code_verifier 交换 access_token

POST https://auth.example.com/token
Content-Type: application/x-www-form-urlencoded

client_id=your-client-id&
grant_type=authorization_code&
code=abcd1234&
redirect_uri=https://yourapp.com/callback&
code_verifier=original-verifier-here

如果 code_verifier 与之前的 code_challenge 匹配,就会发放 access_token:

{
  "access_token": "eyJ....",
  "id_token": "eyJ....",
  "refresh_token": "...",
  "expires_in": 3600,
  "token_type": "Bearer"
}

为什么这样可以保证安全性?

首先临时生成一个 code_verifier,保存在本地,然后将 code_challenge 发给服务端,服务端进行保存,然后换取 access_token 时,再将 code_verifier 提交上去,如果黑客获取了 code_challenge,他也无法进行下一步操作,如果黑客获取了 code_verifier, 他虽然可以获得 access_token,但是无法使用 code_verifier 再次获取,因为 code_verifier 和 code_challenge 是一对临时 生成的随机密钥(准确来说是一个随机值和随机值的哈希值)。

如果是客户端直接保存了 client_secret 那就不一样了,黑客获取之后,总是可以通过 client_secret 和 code 来换取 access_token。 这就是这种模式的安全所在。

此种授权流程的安全性是基于Https的,如果使用http攻击者将很容易获取到 access_token

 

其他补充

Native App中使用Code传参的话直接用原先的方式

  • 1、是绑定URL Scheme通过类似app-name://?code=的方法把code传递给原生客户端;
  • 2、在本地起个HTTP服务器通过http://localhost:port/?code=的方法监听code
  • 直接在Native App里面嵌入Webview来传递,在携带code重定向这个步骤,拦截重定向url,获取code,换取token

全部评论



提问