Web 应用程序和移动应用程序的 REST API 身份验证

Posted

技术标签:

【中文标题】Web 应用程序和移动应用程序的 REST API 身份验证【英文标题】:REST API authentication for web app and mobile app 【发布时间】:2014-02-25 17:28:27 【问题描述】:

我在决定如何为 RESTful API 实施身份验证时遇到了一些麻烦,该 API 对 Web 应用程序和移动应用程序的使用都是安全的。

首先,我想研究基于 HTTPS 的 HTTP 基本身份验证作为一个选项。它适用于移动应用程序,其中用户名和密码可以安全地存储在操作系统钥匙串中,并且由于请求将通过 HTTPS 传输,因此在传输过程中不会被拦截。 API 也很优雅,因为它完全是无状态的。问题在于网络应用程序。将无法访问这样的钥匙串来存储用户名和密码,因此我需要使用 cookie 或 localStorage,但随后我会将用户的私人详细信息存储在易于访问的位置。

经过更多研究,我发现很多关于 HMAC 身份验证的讨论。我看到这种方法的问题是需要一个只有客户端和服务器知道的共享密钥。除非我有一个 api/login 端点,它接受用户名/密码并将密码返回并存储在 cookie 中,否则我如何才能将每个用户的密码获取给 Web 应用程序中的特定用户?在以后的请求中使用。然而,这是向 API 引入状态。

为了将另一个扳手投入工作,我希望能够将 API 限制为某些应用程序(或者,能够阻止某些应用程序使用 API)。如果网络应用完全公开,我看不出这怎么可能。

我真的不想实现 OAuth。对于我的需求来说,这可能有点过头了。

我觉得我可能没有完全理解 HMAC,所以我欢迎解释以及如何使用网络应用程序和移动应用程序安全地实现它。

更新

我最终使用了 HTTP 基本身份验证,但是不是为每个请求提供实际的用户名和密码,而是实现了一个端点来交换用户名和密码以获取访问密钥,然后为每个经过身份验证的请求提供该访问密钥。消除了在浏览器中存储用户名和密码的问题,但当然,如果您可以访问机器并使用它,您仍然可以取出令牌。事后看来,我可能会进一步研究 OAuth,但它对于初学者来说相当复杂。

【问题讨论】:

> 我真的不想实现 OAuth。对于我的需求来说,这可能有点过头了……不,这正是你所需要的 :-) 您是如何解决身份验证问题的? 【参考方案1】:

您应该使用 OAuth2。方法如下:

1) 移动应用

您自己声明的移动应用商店客户端凭据。然后它使用“资源所有者密码凭据授予”(请参阅​​https://www.rfc-editor.org/rfc/rfc6749#section-4.3)发送这些凭据。反过来,它会获得一个(承载)令牌,它可以在以下请求中使用。

2) 网站

网站使用“授权码授予”(见https://www.rfc-editor.org/rfc/rfc6749#section-4.1):

    网站看到未经授权的请求并将浏览器重定向到 REST api 中启用 html 的自动化端点。

    用户使用 REST 服务进行身份验证

    REST 站点使用 URL 中的访问令牌将用户重定向回网站。

    网站调用 REST 站点并将访问令牌交换为授权令牌。

在网站使用授权令牌访问 REST 服务之后(代表最终用户) - 通常通过将令牌作为“承载”令牌包含在 HTTP 授权标头中。

这不是火箭科学,但确实需要一些时间才能完全理解。

3) 限制某些应用程序的 API 访问

在 OAuth2 中,每个客户端都会获得一个客户端 ID 和客户端密码(这里的“客户端”是您的移动应用或网站)。客户端在授权时必须发送这些凭据。您的 REST 服务可以使用它来验证调用客户端

【讨论】:

如何为 Web 应用程序的客户端机密保密?源代码对所有人开放,是什么阻止了有人窃取它以用于未经授权的应用程序? 使用普通的旧服务器配置,不要在任何地方硬编码客户端机密。让网站从不属于源代码存储库的文件中读取秘密。这很简单。它实际上是您应该担心的移动客户端,因为下载它的人可以从中提取客户端密码。我还没有看到解决方案。 @JørnWildt 为什么不对网站也使用“资源所有者密码凭据授予”?实际上,在用户登录后返回刷新令牌和访问令牌允许不存储用户名和密码以供进一步请求,如此处所述:techblog.hybris.com/2012/06/11/… @Mik378 因为 ROPCG 强制最终用户将她的凭据发送到一个不需要它们的网站(为了让该网站在 REST API 上使用她的凭据)。使用 ACG,用户仅将她的凭据发送到实际“拥有”凭据的站点(REST API)。 @JørnWildt:关于“3)限制某些应用程序的 API 访问”,你能告诉我如何在 Asp.Net Web API 2 中做到这一点吗?谢谢。【参考方案2】:

我为自己的 API 轻松安全地解决了这个问题,无需公开任何客户端凭据。

我还将问题分为两部分。 API 身份验证 - 这是来自公认实体(网站或本机应用程序)的有效请求。 API 授权,是允许使用此特定端点和 HTTP 动词的实体。

使用访问控制列表以及根据需要在 API 代码、配置和数据库中设置的用户权限和设置将授权编码到 API 中。 API 中的简单 if 语句可以测试授权并返回适当的响应(未授权或处理 API 调用的结果)。

身份验证现在只是检查呼叫是否真实。为此,我向客户颁发自签名证书。随时从他们的服务器调用 API - 通常是在他们生成他们的第一个页面时(或者当他们执行自己的应用程序登录检查时)。此调用使用我之前提供的证书。如果在我这边我很高兴证书是有效的,我可以返回一个随机数和一个限时生成的 API 密钥。此密钥用于对其他 API 端点的所有后续调用,例如在承载标头中,它可以非常公开地存储在 HTML 表单字段或 javascript 变量或应用程序内的变量中。

nonce 将防止重放攻击,如果有人愿意,API 密钥可能会被盗 - 他们将无法在过期后继续使用,或者如果在他们进行下一次调用之前 nonce 发生更改。

每个 API 响应都将包含下一个 nonce,如果 nonce 不匹配,它将返回身份验证错误。事实上,nonce 不匹配我也杀死了 API 密钥。然后,这将强制真正的 API 用户使用证书重新进行身份验证。

只要最终用户保持这些证书的安全并且不公开他们用于进行初始身份验证调用的方法(例如使其成为可以重放的 ajax 请求),那么 API 就很好且安全。

【讨论】:

您好,您的回答似乎是我真正想使用的东西,您是否知道任何可以引导我了解您所说的方向的教程,谢谢 @CostasAletrari 对不起 - 我没有。我自己在 Lumen 上使用自定义代码完成了所有工作。 这是一个很酷的想法。您如何解决来自不同浏览器选项卡(它们是不同进程)的多个并发请求的问题?此外,如果服务器发送的新 nonce 没有到达客户端(无论出于何种原因),您如何解决这个问题 - 这两种情况都可能导致频繁的烦人重新身份验证(取决于 API 密钥的寿命)。有一篇博客文章有类似的内容,但针对用户会话。它突出了这些问题并讨论了它们的解决方案:hackernoon.com/… 前端应用程序不允许多个并发请求。利用本地存储和承诺,您只需将请求排队,这样它们就必须等待前一个请求的新随机数才能继续。如果没有新的随机数返回(或不匹配),则重新身份验证请求在后台发生,用户不知道它已经发生,【参考方案3】:

解决 API 用户身份验证问题的一种方法是在用户登录时从 API 请求身份验证令牌。此令牌随后可用于后续请求。您已经接触过这种方法 - 它非常合理。

关于限制某些网络应用。您需要让每个 Web 应用程序在每个请求中标识自己,并在您的 API 实现中执行此身份验证。非常直接。

【讨论】:

如果 Web 应用程序和其他应用程序都使用相同的 API 和身份验证机制,什么会阻止某人 A) 窃取用户的身份验证令牌并在其他地方使用它和 B) 冒充 Web 应用程序(或者,如何网络应用程序是否可以免于识别/防止人们伪装成网络应用程序? @Dave,关于限制某些网络应用程序,你说这很简单,但你能告诉我如何在 Asp.Net Web API 2 中做到这一点吗? 限制应用程序是我上面方法中的证书的用途。没有证书,您将无法获得令牌。如果没有令牌,您将无法访问 API 套件的其余部分。您可以通过限制时间并实施随机数检查来阻止人们窃取令牌。

以上是关于Web 应用程序和移动应用程序的 REST API 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何在我的 Web 应用程序中实现 REST。我想为我的网站制作一个休息 API?

从移动设备登录 Spring Security、Rest api 和 Facebook

Rest,Rest Api,Web Service,RestFul Api之间的区别[关闭]

Web 客户端和移动 REST api 安全性的推荐配置

为 web 应用程序使用的 python REST API 选择适当的身份验证类

使用 AWS Cognito 保护 REST API