首页 文章

当“隐式”流程运行良好时,为什么OAuth2中存在“授权代码”流?

提问于
浏览
188

使用“隐式”流程,客户端(可能是浏览器)将在资源所有者(即用户)提供访问权限后获得访问令牌 .

但是,对于"Authorization Code"流,客户端(通常是Web服务器)仅在资源所有者(即用户)授予访问权限后才获取授权代码 . 使用该授权代码,客户端再次调用API,将client_id和client_secret与授权代码一起传递,以获取访问令牌 . All well described here .

两个流都具有完全相同的结果:访问令牌 . 但是,“隐式”流程要简单得多 .

问题: Why bother with "Authorization Code" flow, when "Implicit" flow seams to be fine? Why not also using "Implicit" for webserver?

这对提供商和客户来说都是更多的工作 .

3 回答

  • 7

    tl;dr: 这都是出于安全原因 .

    OAuth 2.0希望满足以下两个标准:

    • 您希望允许开发人员使用非HTTPS重定向URI,因为并非所有开发人员都具有启用SSL的服务器,如果他们这样做,则并非总是正确配置(非自签名,可信SSL证书,同步服务器时钟......) .

    • 您不希望黑客通过拦截请求来窃取访问/刷新令牌 .

    Details below:

    由于安全原因,隐式流只能在浏览器环境中使用:

    implicit flow 中,访问令牌直接作为哈希片段(而不是URL参数)传递 . 关于散列片段的一个重要的事情是,一旦你遵循包含散列片段的链接,只有浏览器知道散列片段 . 浏览器会将哈希片段直接传递到目标网页(重定向URI /客户端的网页) . 散列片段具有以下属性:

    • 它们不是HTTP请求的一部分,因此服务器无法读取它们,因此它们不能被中间服务器/路由器拦截(这很重要) .

    • 它们只存在于浏览器 - 客户端 - 所以读取哈希片段的唯一方法是使用在页面上运行的JavaScript .

    这使得可以将访问令牌直接传递给客户端,而不存在被中间服务器拦截的风险 . 这有一个警告,只有可能是客户端,需要运行客户端的javascript才能使用访问令牌 .

    authorization code flow 中,无法直接在URL参数中传递访问令牌,因为URL参数是HTTP请求的一部分,因此您的请求将通过的任何中间服务器/路由器(可能是数百个)都可以读取如果您没有使用加密连接(HTTPS)允许所谓的中间人攻击,则访问令牌 .

    理论上可以直接在URL参数中传递访问令牌,但是auth服务器必须确保重定向URI使用带有TLS加密的HTTPS和“可信”SSL证书(通常来自非免费的证书颁发机构)确保目标服务器是合法的,并且HTTP请求是完全加密的 . 让所有开发人员购买SSL证书并在其域上正确配置SSL将是一个巨大的痛苦,并将大大减缓采用速度 . 这就是为什么提供中间一次性“授权代码”,只有合法的接收者能够交换(因为你需要客户端秘密),并且代码对潜在的黑客通过未加密的交易拦截请求是无用的 . (因为他们不知道客户的秘密) .

    您还可以认为隐式流不太安全,有潜在的攻击向量,例如在重定向时欺骗域 - 例如通过劫持客户端网站的IP地址 . 这是隐式流仅授予访问权限(它应该具有有限时间使用)并且永远不刷新令牌(其在时间上是无限制的)的原因之一 . 为解决此问题,我建议您尽可能在支持HTTPS的服务器上托管您的网页 .

  • 0

    Implicit Flow makes the whole flow pretty easy, but also less secure .
    由于客户端应用程序(通常是在浏览器中运行的JavaScript)不太受信任,因此不会返回用于长期访问的刷新令牌 .
    对于需要临时访问(几个小时)用户数据的应用程序,您应该使用此流程 .
    将访问令牌返回给JavaScript客户端也意味着您的基于浏览器的应用程序需要特别小心 - 想想可能将访问令牌泄漏到其他系统的XSS攻击 .

    https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow

  • 218

    来自OAuth spec的第4.2段:

    隐式授权类型用于获取访问令牌(它不支持刷新令牌的发布),并且针对已知操作特定重定向URI的公共客户端进行了优化 . 这些客户端通常使用脚本语言(如JavaScript)在浏览器中实现 .

    作为基于重定向的流,客户端必须能够与资源所有者的用户代理(通常是Web浏览器)进行交互,并且能够从授权服务器接收传入请求(通过重定向) .

    与授权代码授权类型不同,客户端在其中单独发出授权和访问令牌请求,客户端会根据授权请求接收访问令牌 .

    隐式授权类型不包括客户端身份验证,并且依赖于资源所有者的存在和重定向URI的注册 . 由于访问令牌被编码到重定向URI中,因此它可能会暴露给资源所有者和驻留在同一设备上的其他应用程序 .

    所以我们可以调整:

    • 这适用于公共OAuth,即客户不需要注册且没有自己的客户机密 . 但是auth服务器检查重定向URL是什么,这实际上足以保证安全性 .

    • 访问令牌出现在浏览器的地址栏中,因此用户可以复制该URL并发送给其他人,并且它也会以用户身份登录,即类似于会话固定 . 但是浏览器会进行额外的重定向,替换历史记录以从网址中删除哈希片段 . 黑客也可以通过嗅探HTTP流量来窃取访问令牌,但这可以通过HTTPS轻松保护 . 某些恶意浏览器扩展可以从地址栏访问URL,但这最终是糟糕的情况,例如破坏的HTTPS证书 . 甚至Auth代码流也无法帮助以太 . 所以我可以看到,通过url的哈希片段传递访问令牌是绝对安全的 .

    • 使用HTTPS时,临时访问令牌和刷新令牌的分离是无用的,说实话,即使在原始HTTP上也没那么有用 . 但是客户端通过隐式流程无法接收刷新令牌这一事实也是无稽之谈 .

    因此,我认为我们应该引入一个新的授权流程“安全隐式”,它严格地通过https工作,允许刷新令牌(或者我们应该完全摆脱它们),并且优于Auth Cose授权流程

相关问题