无需用户身份验证(无凭据)的安全 REST API

Secure REST API without user authentification (no credentials)

我已经为如何在没有用户身份验证的情况下保护 REST API 苦苦挣扎了 2 天。

什么意思?

在我的 AngularJS 应用程序中,我通过向我必须使用的现有服务 (companydomain/userinfo) 发送 GET 请求来识别用户。我不确定这是如何工作的,因为我不是这段代码的作者,但重点是我在响应中获得有关用户的信息 JSON(活动目录名称,phone在公司...).

这就是我识别用户的全部内容。

我做了什么

现在,我发现很多资源都在讨论 OAuth、唯一令牌等,但似乎没有任何内容与我的问题相符。我实现了一个令牌系统,但它毫无用处,因为我无法确定请求者的真实性。

  1. 用户打开应用程序。应用程序向服务询问与用户相关的信息。 companydomain/userinfo
  2. 应用程序根据返回的信息向服务器(nodejs 和 express)请求令牌。 /api/token/get/{user_info}
  3. 服务器生成一个唯一的令牌并将其与过期日期和所有者一起存储在内存中。服务器还会检查 table "authorized users" 用户是否存在(基于活动目录名称),如果不存在则向其添加新条目。
  4. 应用程序将令牌随每个请求一起发送到 API。 /api/entry/delete/{entry_id}

我想你明白这里出了什么问题,攻击者可以轻松地向 API 发出损坏的请求以获取合法令牌。所以我的问题是:

由于用户不使用凭据进行身份验证,我如何设法保护我的 API?

我希望我的问题足够清楚,此时我什至不确定我是否可以在不添加凭据系统的情况下解决这个问题。

您可能想看看 Passport。它是一个允许您轻松向应用程序添加身份验证的平台。有许多可用的身份验证策略。我在实施我自己的 hmac 策略的 Node.js 应用程序中使用 Passport。

为了进行身份验证,客户端请求包括一个 API ID 以识别调用者是谁,还包括消息指定部分的签名,其中包括 HTTP 方法、API ID、日期值和其他一些 header 值,例如 content-type。要签名的字符串中包含哪些数据由您在实现中自行决定,但客户端和服务器必须创建并签署相同的字符串才能使身份验证生效。签名是通过使用共享密钥对字符串进行 hmac 哈希来创建的。

在服务器端,您使用 API ID 检索共享机密(可能来自数据库或文件系统)并对请求执行相同的散列。如果 hmac 值匹配,那么您已经对请求进行了身份验证。为防止回放攻击,日期包含在请求的签名部分,并且必须在服务器当前时间的某个 window 范围内。例如,如果时间戳超过 30 秒,您可能会拒绝请求。

要启用您的 API 的新用户,您需要生成一个新的 API ID 和共享密钥。您将这两个都提供给 API 用户,然后存储它们以供在数据库或文件系统中查找。用户必须使用共享密钥签署请求并在请求中包含 ID。

Hawk strategy 提供了很多这样的功能,但我们决定推出我们自己的 hmac 策略。

因为你说用户信息端点 returns 活动目录名称,我假设你在 Windows 平台上。

如果是这样,为什么不使用 Windows integrated authentication (Kerberos) 来验证您的用户而不要求他们提供凭据?这将仅在您的活动目录域内工作,但对您的服务是完全透明的。

您仍然可以调用用户信息端点并验证它 returns 的信息是否针对调用您的 REST 服务的同一用户。

如果您需要调用不支持 Windows 集成身份验证的服务,您可以生成一个 security token(签名以保证完整性)并让其他服务信任此令牌。