再也不用分享密码——OAuth 2.0 解决方案

💡 原文英文,约800词,阅读约需3分钟。
📝

内容提要

OAuth 2.0 解决了“密码反模式”:过去第三方应用需用户直接交出密码,一旦泄露则全账户失守且无法单独撤销;OAuth 让用户只在可信服务方登录,应用获得有范围、限时、可撤销的令牌。标准流程为授权码加 PKCE:重定向授权、用户认证、返回短期授权码、服务端换取令牌、携带令牌调用 API。state 防 CSRF,code_challenge 防授权码拦截,固定 redirect_uri 防劫持,授权码一次性且短效;scope 将全部权限收窄为特定权限,降低泄露风险。

🔎

延伸解读

从“交出密码”到“发放令牌”的转变

文章指出,OAuth 2.0 之前第三方应用需要用户直接提供账号密码,一旦应用被攻破,所有相关账户都会失守,用户也无法单独撤销某个应用的访问权。OAuth 2.0 让用户只在可信服务方登录,第三方应用获得的是有范围、限时、可撤销的令牌,密码不再离开授权服务器。这一转变的核心是把“全部账户权限”收窄为“特定权限”,从而在协议层面降低泄露后的影响范围。

四个参数各自封堵一类攻击

文章强调授权码加 PKCE 流程中有四个安全关键参数:state 用于防止 CSRF,避免攻击者把其账户绑定到用户会话;code_challenge 与 code_verifier 用于 PKCE,使被拦截的授权码因缺少匹配的 verifier 而失效;固定 redirect_uri 防止授权码被劫持到恶意地址;授权码一次性且仅数十秒到两分钟有效,即使被记录也无法复用。文章提醒,不检查 state 是现实中常见的 OAuth 漏洞之一。

scope 把“全部”变成“一件具体的事”

文章以 scope=calendar.read 为例说明,该权限只允许读取日历,不能删除事件、发送邮件、访问联系人或代用户发帖。即使应用日后被攻破,攻击者获得的也只是受限于该范围的读取权限。文章认为,安全工作的本质就是把“一切权限”转化为“某一具体权限”,而 scope 正是 OAuth 2.0 在协议层面实现这一收窄的方式,与 OAuth 之前应用拥有完整账户权限的情况形成对比。

❓

Q&A

OAuth 2.0 解决了什么问题?

OAuth 2.0 解决了“密码反模式”问题:过去第三方应用需要用户直接提供密码,一旦应用被攻破,所有用户账户都会失守,且用户无法单独撤销某个应用的访问权限。OAuth 2.0 让用户只在可信服务方登录,第三方应用获得的是有范围、限时、可撤销的令牌,而非密码。

OAuth 2.0 的授权码流程具体步骤是什么?

标准流程为授权码加 PKCE,共五步:1) 应用将用户重定向到授权服务器;2) 用户在授权服务器上认证;3) 授权服务器重定向回应用并返回短期授权码;4) 应用在服务端用授权码换取令牌;5) 授权服务器返回令牌,应用携带令牌调用 API。

OAuth 2.0 中的 state 参数有什么作用?

state 参数用于防止 CSRF 攻击。应用生成一个随机值,在授权请求中发送,并在重定向返回时检查该值是否一致。如果不检查 state,攻击者可能诱骗已登录用户完成攻击者的 OAuth 流程,将攻击者账户绑定到用户的应用会话上。

PKCE 如何防止授权码被拦截?

PKCE 通过 code_challenge 和 code_verifier 机制防止授权码拦截。应用生成随机 code_verifier,将其 SHA-256 哈希作为 code_challenge 在授权请求中发送,然后在换取令牌时提供原始 code_verifier。攻击者即使拦截了授权码,没有匹配的 code_verifier 也无法使用。

OAuth 2.0 的 scope 有什么作用?

scope 将权限从“全部”收窄为“特定”。例如 scope=calendar.read 表示应用只能读取日历,不能删除事件、发送邮件或访问联系人。即使应用被攻破,攻击者也只能获得有限权限,降低了泄露风险。

OAuth 2.0 令牌有哪些重要属性?

OAuth 2.0 令牌有三个重要属性:1) 有范围(Scoped)——只授予用户批准的特定权限;2) 限时(Time-limited)——通常一小时内过期;3) 可撤销(Revocable)——用户可随时从账户设置中撤销。

🏷️

标签

➡️

继续阅读