Public Client上的客户端身份验证

Enr*_*ico 23 oauth-2.0

学习OAuth2.0我终于找到了这两个参考:

http://tools.ietf.org/html/rfc6749#section-2.3

http://tools.ietf.org/html/rfc6749#section-10.1

如我错了请纠正我:

可以使用未注册的客户端,但您必须自己管理安全风险.

  • 我该如何管理它们?

一些更具体的问题:

  1. 机应用程序(确实公共客户端)无法定义安全存储其凭据(client_id + secret).它是未注册的客户吗?如果我无法使用秘密对其进行验证/验证,我还应该做些什么?
  2. 客户端注册=/=端点注册:第一个是关于注册Client Credentials(client_id + secret); 第二个关于注册客户端重定向端点.重定向端点注册是否足以授予客户端的真实性?
  3. Client Credential Grant是否使用相同的凭据(client_id + secret)进行客户注册?

我想你可以回答我只是解释一下这段http://tools.ietf.org/html/rfc6749#section-10.1

请报告如何实施的参考和实际例子:

[...]它超出了本规范的范围.

谢谢

pva*_*nde 36

TL;博士:

  1. 本机客户端无法使用client_id和进行身份验证client_secret.如果您需要对客户端进行身份验证,则必须实现一种身份验证方案,该方案不会将共享密钥委托给客户端(或者让最终用户参与客户端身份验证讨论).根据应用程序的安全模型,您可能不需要对客户端进行身份验证.
  2. 重定向端点通常不足以验证客户端(尽管存在异常).
  3. "客户端凭证"授权类型可以使用授权服务器支持的任何客户端认证机制,包括在客户端注册时给出的凭证.

正如我所读到的那样,要点是您可以信任机密客户端client_id(读取:"用户名")和client_secret(读取:"密码")以使用您的服务对其进行身份验证.第三方应用程序没有[1]机会用该客户端的凭证代表自己,因为它们被合理地假设安全存储远离窥探的眼睛.

然而,公共客户端无法做出这样的保证 - 无论是基于浏览器的应用程序还是本机桌面应用程序,客户端的id和秘密都会分发给全世界.可以合理地假设这样的应用程序将最终掌握在熟练的开发人员和黑客手中,他们可以深入了解客户端并提取id和秘密.出于这个原因,第10.1节明确指出:

The authorization server MUST NOT issue client passwords or other
client credentials to native application or user-agent-based
application clients for the purpose of client authentication.
Run Code Online (Sandbox Code Playgroud)

好的.因此,公共客户端无法通过密码进行身份验证.然而…

The authorization server MAY issue a client password or other
credentials for a specific installation of a native application
client on a specific device.
Run Code Online (Sandbox Code Playgroud)

此例外有效,因为它将客户端的身份验证与特定设备联系起来,这意味着即使有人离开了客户端的秘密,他们也无法重复使用它.但是,在此例外中隐含的是"特定设备上的特定安装"必须是唯一可识别的,难以欺骗的,并且是该客户端的身份验证过程的组成部分.

并非每个本机应用程序都能满足这些标准,并且基于浏览器的应用程序当然不能,因为在运行的环境中没有任何可识别的或难以欺骗的东西.这会导致一些选项 - 您可以将客户端视为未经身份验证,或者您可以提供更合适的身份验证机制.

身份验证舞蹈的关键是共享秘密 - 只有授权服务器和身份验证客户端才知道. 对于公共客户来说,客户本身并不是秘密. 值得庆幸的是,有一些选择,我不只是谈论RFID密钥卡和生物识别技术(尽管这些都是完全可以接受的).

作为一个思想实验,让我们考虑一个基于浏览器的客户端.我们可以合理地假设一些事情:它在浏览器中运行,它是从特定域提供的,并且该域由客户端的作者控制.身份验证服务器应该已经有一个客户端重定向URI,所以我们有一些东西,但是当规范调用时:

A valid redirection URI is not sufficient to verify the client's
identity when asking for resource owner authorization but can be
used to prevent delivering credentials to a counterfeit client
after obtaining resource owner authorization.
Run Code Online (Sandbox Code Playgroud)

所以重定向URI是我们应该检查的东西,但不是我们可以信任的东西,很大程度上是因为域可能是欺骗性的.但是服务器本身不可能,所以我们可以尝试向域询问只有客户端域的服务器才知道的东西.最简单的方法是让身份验证服务器在与客户端相同的域上需要第二个("私有")URI,客户端的秘密将托管在该客户端上.当客户端应用程序的授权请求,服务器则"检查中"针对第二URI 相对于客户端的报告的主机名,并查找共享密钥(这应该永远只能透露给授权服务器的IP地址)来验证客户.

当然,这不是一个完美的解决方案.它并不适用于每个应用程序,它很容易出错,并且可能需要执行很多工作.存在许多潜在的认证机制(高度特定和高度通用),并且任何不委托客户端应用程序使用私有数据的机制都适用于该问题空间.

我们的另一个选择是不执行进一步的身份验证,并将客户端视为未经身份验证.这是特别一样的东西作为一个未注册的客户端,但不同的是微妙的.未注册的客户端是其身份未知的客户端.未经身份验证的客户端是一个客户,其身份已知,但不可信.两种类型的客户端的安全含义是相同的:既不应该委托私有数据.然而,授权服务器是否选择将这两种情况视为相同,似乎由实施者来决定.例如,API可能有意义拒绝来自未注册客户端的所有连接,并将公共只读内容提供给任何已注册的客户端(即使不验证客户端的身份).

实用主义,但是,仍有可能胜出-未经认证的客户端是根本没有比SSL的"错误",你会偶尔会看到当你的浏览器无法验证该网站的SSL证书的真实性不同.浏览器将立即拒绝继续进行并准确报告原因,但允许用户通过担保服务器的身份来接受风险.类似的工作流程可能对许多OAuth2应用程序有意义.

无论如何,为什么验证客户的身份很重要?如果不这样做,信任链就会被打破.您的应用程序的用户信任您的应用程序.授权工作流程确定您的用户也信任客户端,因此您的应用程序应该信任客户端.在不验证客户端身份的情况下,另一个客户端可以出现并承担可信客户端的角色,并具有其所有安全权限.有关客户端身份验证的所有信息都可以防止信任遭到破坏.

希望这有帮助!

[1]:服务器泄露,应用程序的源代码落入恶意手中,是一个例外,并且内置了其他保护措施.话虽如此,规范还特别指出简单的用户名/密码组合不是最安全的选择:

The authorization server is encouraged to consider stronger
authentication means than a client password.
Run Code Online (Sandbox Code Playgroud)

  • 那么@pvande,有没有任何解决方案来验证桌面应用客户端?我甚至在你的回答中看不到任何一个: (2认同)
  • @pvande我还是很困惑.如果client_id/client_secret遭到破坏(说它在​​浏览器应用程序中被硬编码),黑客仍然必须知道用户的凭据才能获得access_token.如果黑客拥有用户凭据,为什么他会担心client_id/client_secret? (2认同)