实现 2 Legged OAuth Provider
Posted
技术标签:
【中文标题】实现 2 Legged OAuth Provider【英文标题】:Implementing a 2 Legged OAuth Provider 【发布时间】:2011-02-02 04:06:11 【问题描述】:我正试图找到解决 OAuth 规范、它的要求以及我能找到的任何实现的方法,到目前为止,它看起来确实比它的价值更麻烦,因为我很难找到一个可以拉动的资源这一切都在一起。或者也许只是我在寻找比大多数教程更专业的东西。
我有一组现有的 API——一些在 Java 中,一些在 php 中——我现在需要保护它们,并且出于多种原因,OAuth 似乎是正确的方法。不幸的是,我无法找到正确的资源来帮助我启动并运行供应商,这对这一理论提出了挑战。由于其中大部分将是系统到系统的 API 使用,因此我需要实现一个 2-legged 提供程序。考虑到这一点...
-
有谁知道使用 PHP 实现 2-legged OAuth 提供程序的任何好的教程?
鉴于我有 2 种语言的安全 API,我是否需要同时实现这两种语言的提供程序,或者是否有办法将提供程序创建为“前端控制器”,我可以通过它汇集所有请求?
例如,在保护 PHP 服务时,我是否必须通过在每个 API 上包含必要的提供程序资源来单独保护每个 API?
感谢您的帮助。
【问题讨论】:
【参考方案1】:Rob,不确定你在哪里找到这个问题,但想加我的 2 美分,以防其他人遇到这个问题。
几个月前我或多或少有同样的问题,并且在一年的大部分时间里听说过“OAuth”。我正在开发一个我需要保护的 REST API,所以我开始阅读有关 OAuth 的内容......然后我的眼睛开始在我的脑海中向后滚动。
我可能花了一两天的时间浏览和阅读它,直到我像你一样决定 OAuth 是令人困惑的垃圾并放弃了它。
然后我开始研究一般保护 API 的方法,并开始更好地掌握如何做到这一点。最流行的方式似乎是向 API 发送请求以及整个消息(使用只有您和服务器知道的秘密编码)的校验和,服务器可以使用该校验和来决定消息是否在来自客户端的途中被篡改,如下所示:
-
客户端发送 /user.json/123?showFriends=true&showStats=true&checksum=kjDSiuas98SD987ad
服务器获取所有信息,在数据库中查找用户“123”,加载他的密钥,然后(使用客户端使用的相同方法)根据请求参数重新计算其 OWN 校验和。
如果服务器生成的校验和与客户端发送的校验和匹配,则请求OK并执行,否则认为被篡改并拒绝。
校验和称为 HMAC,如果您想要一个很好的例子,它就是 Amazon Web Services 使用的(虽然他们称参数为“签名”而不是“校验和”)。
因此,鉴于此工作的关键组件之一是客户端和服务器必须以相同的方式生成 HMAC(否则它们将不匹配),必须有关于如何组合所有参数...然后我突然从 OAuth 中理解了所有“参数的自然字节顺序”的废话...它只是定义了如何生成签名的规则,因为它需要。
另外一点是,您在 HMAC 生成中包含的每个参数都是一个值,因此在您发送请求时无法篡改。
因此,如果您只是将 URI 词干编码为签名,例如:
/user.json == askJdla9/kjdas+Askj2l8add那么您的消息中唯一不能被篡改的是 URI,所有参数都可以被篡改,因为它们不是服务器将重新计算的“校验和”值的一部分。
或者,即使您在计算中包含每个参数,您仍然会面临“重放攻击”的风险,在这种风险中,恶意中间人或被窃听者可以拦截 API 调用,然后一遍又一遍地将其重新发送到服务器。
您也可以通过在 HMAC 计算中添加时间戳(始终使用 UTC)来解决此问题。
提醒:由于服务器需要计算相同的 HMAC,因此您必须发送您在计算中使用的任何值,除了您的密钥(我认为 OAuth 将其称为 consumer_secret)。因此,如果您添加时间戳,请确保在您的请求中发送时间戳参数。
如果您想让 API 免受重放攻击,您可以使用 nonce 值(它是服务器生成的 1 次使用值,提供给客户端,客户端在 HMAC 中使用它,发回请求,服务器确认然后在数据库中将该 nonce 值标记为“已使用”,并且永远不会让另一个请求再次使用它。
注意:“nonce”是解决“重放攻击”问题的一种非常精确的方法——时间戳很好,但由于计算机并不总是具有同步的时间戳值,因此您必须在在我们接受或拒绝请求之前,服务器端的请求可能有多“旧”(比如 10 分钟、30 分钟、1 小时……亚马逊使用 15 分钟)。在这种情况下,您的 API 在整个时间范围内都存在技术漏洞。
我认为 nonce 值很棒,但只需要在对它们保持完整性至关重要的 API 中使用。在我的 API 中,我不需要它,但是如果用户需要它,以后添加它会很简单......我实际上只需要在我的数据库中添加一个“nonce”表,向客户端公开一个新的 API,例如:
/nonce.json然后当他们在 HMAC 计算中将其发回给我时,我需要检查数据库以确保它以前从未使用过,并且一旦使用过,在数据库中将其标记为这样,这样如果有请求出现再次使用相同的随机数我会拒绝它。
总结
总之,长话短说,我刚才描述的一切基本上就是所谓的“2-legged OAuth”。没有向授权机构(Twitter、Facebook、谷歌等)授权客户端的额外步骤,该步骤被删除,而是服务器隐式信任客户端,如果他们发送的 HMAC 匹配。这意味着客户端拥有正确的 secret_key 并且正在使用它对消息进行签名,因此服务器信任它。
如果您开始在线查看,这似乎是当今保护 API 方法或类似方法的首选方法。亚马逊几乎完全使用这种方法,只是他们在对整个事物进行签名以生成 HMAC 之前对其参数使用了稍微不同的组合方法。
如果你有兴趣,我wrote up this entire journey 和我正在学习的思考过程。这可能有助于为这个过程提供一个有指导的思维导览。
【讨论】:
很高兴看到您是如何决定不使用 OAuth 并最终获得 2legged OAuth 的各个方面的。 很好的解释,我也做过类似的事情。自定义您自己的解决方案有很多好处,您可以使其仅适用于您想要的服务。我没有实现随机数,但也许我应该看看。 +1,尤其是您的博客条目thebuzzmedia.com/…【参考方案2】:我会退后一步,想一想经过适当身份验证的客户将向您发送什么。
您能否将密钥和凭据存储在可从两组服务访问的通用数据库中,并仅以一种语言实现 OAuth 提供程序?当用户向服务(PHP 或 Java)发送请求时,您将检查公共存储。当用户设置 OAuth 客户端时,您可以通过 PHP 或 Java 应用程序(您的偏好)完成所有这些操作,并将凭据存储在公共数据库中。
您可能想查看一些用其他语言编写的 Oauth 提供程序:
PHP - http://term.ie/oauth/example/(见页面底部) 红宝石 - http://github.com/mojodna/sample-oauth-provider .NET http://blog.bittercoder.com/PermaLink,guid,0d080a15-b412-48cf-b0d4-e842b25e3813.aspx【讨论】:
我可能会共享一个数据存储,但我认为这意味着我别无选择,只能以多种语言实现提供程序(或者我想是建立一个前端控制器)。到目前为止,从我对 OAuth 的了解(很少)来看,我认为可能是这种情况,但希望是错误的。同样,看起来我必须通过包含必要的提供程序文件 (PHP) 来独立保护每个 API。那是对的吗?感觉非常笨重。 在使用 PHP 提供程序库一天左右但一无所获之后,我认为 OAuth 根本不值得加重。将此标记为答案,因为它确实提供了一些很好的信息。以上是关于实现 2 Legged OAuth Provider的主要内容,如果未能解决你的问题,请参考以下文章
2-legged oauth 在 OAuth 2.0 中如何工作?
使用 spring-boot-starter-oauth2-client 检索 OAuth2 3-legged 身份验证的访问令牌
在 .NET 中使用 OAuth2.0 2-legged 方法访问 Jira API
带有 2-legged OAuth 的 Gmail atom 提要收到 401 错误