OAuth 2.0授权码授予(无秘钥)

9
所以我一直在研究使用 Microsoft cordova-plugin-ms-adal 插件(使用原生库)为 Cordova 移动应用程序设置 OAuth 2.0,针对使用 Azure AD 的自定义 API。这一切都很顺利,但是我有点困惑于密钥的使用(或更具体地说,它的缺失)。
在网上的许多文章中,他们指出在使用授权代码授予并请求令牌时,需要包括密钥。并且当您可以安全地存储密钥时,此授权类型非常理想。
然而,该插件不需要在应用程序中指定密钥(也是正确的),但它仍然使用授权代码授予进行身份验证。同时,我可以手动调用。
https://login.windows.net/common/oauth2/authorize?resource=http://***.onmicrosoft.com/***API&client_id=***&response_type=code&redirect_uri=http://***.onmicrosoft.com/***App

在我的浏览器中,登录并获取代码,然后使用POST方法将其发送到https://login.windows.net/common/oauth2/token

grant_type: authorization_code
client_id: ***
code: ***
redirect_uri: http://***.onmicrosoft.com/***App
resource: http://***.onmicrosoft.com/***API

并且它可以正常工作,所以我收到了一个有效的JWT,无需发送密码。为什么呢?这样安全性会降低吗?(我还注意到OAuth 2.0规范第4.1.3节没有说明授权码授权类型需要密码!?)没有密码/基本认证头使用授权码授权类型有哪些影响?

你能告诉我你是如何在浏览器登录中获取代码的,以及你是使用JavaScript还是任何服务器端语言进行POST的吗?我遇到了这个问题,需要你的帮助!!! - Sourav Das
@SouravDas 为了更好地理解,我手动调用了端点。一旦在浏览器中调用第一个URL并登录,它将重定向到您已配置的redirect_uri,并带有?code=参数。在POST到令牌端点时使用此值-我使用https://www.getpostman.com进行测试。在我的实际代码中,我设置了cordova-plugin-ms-adal插件来处理这个过程! - Ross
谢谢您的回复。我们使用的是ADFS而不是AZAD,所以我想我必须写整个东西!! - Sourav Das
3个回答

12

对于使用所谓机密客户端(具有客户端密码的客户端)进行授权代码授予与使用公共客户端相比,更加安全。

这是因为授权代码本身的交换作为前通道中的URL参数在浏览器中发生,因此相对容易受到攻击,例如跨站脚本、点击劫持、网络/DNS操纵等等。这意味着在某些情况下(用户粗心、攻击者网络控制、服务器实现中的重定向URI匹配不严格等),有专门的攻击者可能窃取用户的授权代码。

为了使用授权代码换取访问令牌,机密客户端必须在HTTPs保护的调用中同时呈现客户端密码和授权代码,而公共客户端没有任何手段确保它确实是指定的客户端。

这意味着攻击者相对容易模仿公共客户端,因为这只需要非机密信息(他可以从自己的浏览器中获取client_id和redirect_uri),以及可以通过上述攻击获取的授权代码。

虽然对于机密客户端来说,获取授权代码的方式也是类似的,但攻击者无法使用它并将其换成访问令牌,因为为了这样做,他需要客户端密码,而攻击者通常很难获得。密码通常存储在后端存储中,并且只通过安全的HTTPs通道进行通信,因此不会泄漏。


5
在使用grant_type=authorization_code(或任何其他流程)与公共客户端(没有秘密或以任何其他方式进行身份验证的客户端)时,其含义是授予的访问令牌不代表客户端直接访问资源的授权,而是代表客户端代表用户访问资源的授权。
这就是为什么在Azure AD中,当您注册本地客户端应用程序(公共客户端)时,您只能将其配置为具有对资源的委派权限,而不是应用程序权限的原因。

1
不需要发送密码。但实际上,在您发布的链接中,请求还包括以下内容: Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW 也许您没有注意到。这显示了使用HTTP基本身份验证以编码形式传输的client_secret
服务器决定客户端如何进行身份验证(如果需要)。根据规范:
如果客户机类型为机密或客户机已发出客户机凭据(或分配其他身份验证要求),则客户机必须按照第3.2.1节的描述对授权服务器进行身份验证。
Sec 3.2.1指向第2.3节(真的),其中提到:
客户端持有客户端密码时可以使用[RFC2617]中定义的HTTP基本身份验证方案来对授权服务器进行身份验证。
客户端密码又称客户端密钥。
因此,密码正在被传输。

1
谢谢Tomas。我承认在规范示例中没有注意到这一点!我想知道的是:如果没有使用秘密/基本身份验证头,使用授权代码授予类型会有什么影响?(我已更新我的问题以反映这一点。) - Ross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接