一步一步走 PKCE 流程
一句话总结
PKCE是将“这个代码是我发起请求的代码”的证明附加到授权代码上的装置。即使没有秘密,代码被窃取也会变得无效。
为什么需要这个?
在移动应用程序中以自定义URL模式接收回调的时代,恶意应用程序注册相同的模式来拦截授权码的攻击实际上是可能的。因为只要有代码就可以获得令牌(因为公开客户端没有秘密)。
PKCE解决了这个问题。即使截获代码,也无法获得令牌。
怎么行动
按照顺序看流程的话是这样的。
首先客户端随机字符串code_verifier创建。43个字以上128个字以下,只写URL安全字符。这个值只有客户端知道。
接下来code_challenge = BASE64URL(SHA256(code_verifier))计算。在授权请求URL上code_challenge哇code_challenge_method=S256发送。plain虽然方法和规格都有,但因为不进行哈希,所以没有意义。
用户在认证服务器上登录的话redirect_uri因为代码回来了。这时state一起回来的时候,一定要确认和客户第一次发送的值是否一样。如果不一样,那不是自己发起的要求。
最后,在代币端点上,与授权代码一起原件code_verifier发送。服务器重新计算并保存了哈希值。code_challenge和比较。对的的话会给代币。
即使攻击者截获了代码code_verifier因为不知道,所以交换失败。
在现场相遇的样子
在重定向URI注册中经常发生错误。http://localhost:*我https://example.com/*如果注册相同的宽域野生卡,即使该域只有一个打开的重定向器,也会泄露令牌。注册正确的路径是原则。
刷新令牌的旋转也是实务的基本。每次更新都会给出新的刷新令牌,使旧令牌失效。如果旧令牌再次使用,会怀疑被盗,并终止整个会话。作者的建议组合是短访问令牌(5~15分钟)和刷新令牌的旋转——即使没有黑名单也能获得实质性的失效效果。
而且值得考虑BFF模式。这种方式完全不将令牌交给浏览器,而是由后端保管,只通过会话cookie进行通信。XSS攻击导致令牌被盗的途径本身就会消失。
PKCE阻止的事情
如果使用没有PKCE的authorization code流,在代码被写入redirect URL时
可以截图。在移动应用程序中,可以自定义模板(myapp://)被其他应用程序遮挡
可以,特别危险。
1. 클라이언트가 무작위 verifier 를 만든다
verifier = base64url(random(32~96 bytes))
2. challenge = base64url(sha256(verifier)) ← 이것만 보낸다
3. 인가 요청에 challenge 를 실어 보낸다
4. 코드를 받아 토큰으로 바꿀 때 verifier 를 보낸다
5. 서버가 sha256(verifier) == challenge 인지 확인
因为截获代码的攻击者不知道verifier,所以不能用令牌换成。哈希的 单向性保证了这一点。
code_challenge_method必须S256写。plain将verifier保持原样
因为是发送的,所以什么都阻止不了。
**现在也建议在网络应用程序中使用PKCE。**以前只有公开客户端(移动·SPA)才有 虽然如此,OAuth 2.1要求所有authorization code流。
state和nonce阻止其他东西
三人很容易混淆,但各自挡住不同的攻击。
| 价格 | 阻止 | 在哪里确认 |
|---|---|---|
state |
CSRF — 将别人的登录附加到我的会话 | 返回重定向时 |
nonce |
ID代币播放攻击 | ID代币的索赔 |
| PKCE | 窃取授权代码 | 交换代币时 |
三个都写入。 state 保存在会话中,并与返回的值进行比较,nonce 是 因为ID代币里面是原封不动地写着的,所以确认一下那个。
重定向URI必须完全匹配
这是最常见的设置错误。认证服务器注册的URI和请求的URI只有一个字符 应该一样。
등록: https://app.example.com/callback
요청: https://app.example.com/callback/ ← 슬래시 하나 차이로 거절
不使用Wildcard。https://app.example.com/*允许的话,该域名的
可以发送任何路径或代码,一个XSS就会泄露代码。
本地开发是http://localhost:3000/callback像这样注册端口。端口
如果变更的话,需要重新注册,所以最好让团队固定开发用的端口。
下次实习要做的事情
用curl和脚本完成PKCE流程的整个过程。创建verifier和challenge,发送授权请求,POST登录表单接收代码,用token交换,甚至确认用错误的verifier失败。然后在单独的练习中将该token验证的中间件粘贴到FastAPI应用程序上。