【问题标题】:Consuming own API for web app - Authentication process with OAuth2为 Web 应用程序使用自己的 API - 使用 OAuth2 的身份验证过程
【发布时间】:2016-09-30 10:15:31
【问题描述】:

概述

我目前正在为一个图像共享应用程序创建一个 API,该应用程序将在网络上运行,并且将来某个时候在移动设备上运行。我了解 API 构建的逻辑部分,但我仍在努力满足自己对身份验证部分的要求。

因此,我的 API 必须可供全世界访问:具有访客访问权限的用户(例如,未登录的人可以上传)以及注册用户。因此,当注册用户上传时,我显然希望用户信息与请求一起发送,并通过我的数据库中的外键将该用户信息附加到上传的图像。


通过 OAuth2 进行身份验证 - 实现

我已经了解 OAuth2 是 API 身份验证的最佳选择,因此我将实施这一方法,但我真的很难解决如何处理 my em>情况。我想过使用client credentials 授权并为我的网络应用程序生成仅一个 凭据集,并让它使用client secret 向API 发送请求以获取访问令牌并让用户执行东西。用户注册过程本身将使用此授权处理。

但是当用户注册并登录时呢?我现在如何处理身份验证?这需要另一笔拨款来接管吗?我正在考虑在用户登录期间进行一些授权过程,以生成新的访问令牌。这种做法有错吗?


我需要什么帮助

我需要您就如何为我的案例正确处理身份验证流程提供意见。这种双向认证过程可能不是我需要的,但这是我理解的方式。非常感谢您的支持。

【问题讨论】:

  • 您正在为您的 API 构建什么样的客户端?它是从浏览器调用您的 API 的 JavaScript 应用程序吗?还是在服务器上运行?
  • @MvdD 这将是一个调用 API 的 Javascript Web 应用程序,是的。
  • @Aborted 澄清一下,当您说“我的网络应用程序”时,您指的是在浏览器中运行的 javascript 应用程序?
  • @kag0 是的,我说的是一个完全用 Javascript 制作的 ReactJS 网站。
  • @Dugi - 只是好奇:你最终使用了什么解决方案?

标签: authentication oauth-2.0 credentials api-design user-accounts


【解决方案1】:

你的方法似乎可行。

Oauth2 有 4 个主要部分:

  • 资源服务器(您的 API)
  • 资源所有者(在资源服务器上拥有数据的最终用户)
  • 授权服务器(获取授权并颁发令牌)
  • 客户端(您的网络应用 - 以及未来的应用)

请记住Client Credentials 授权,您获得的令牌可能没有任何用户上下文。因此,如果您的 API 端点依赖于令牌中包含的用户标识符/资源所有者,那么您将需要围绕该类型的令牌编写代码。

如果您确实需要令牌来为您的 API 提供一些资源所有者上下文,并且您的 Web 应用程序恰好是您的身份提供者,那么您可以使用 resource owner password 授权,它将为您提供令牌和刷新令牌资源所有者/用户的上下文。

Authorization code 授权很好,前提是您未来的 API 使用者是 Web 应用程序(即在服务器上运行)。如果您计划允许移动/原生应用程序使用您的 API,那么您应该考虑在您的授权服务器中允许 Implicit 授予。

如果您的 API 没有最终用户,并且每个客户端对 API 的访问权限因应用程序的不同而不同,那么您可以使用客户端凭据授权并使用 scopes 来限制 API 访问权限。

编辑

所以我的 API 必须可以通过访客访问(非 例如,登录的人可以上传)和注册用户。所以 当注册用户上传时,我显然希望发送用户 连同请求并将该用户附加到上传的图像

要实现这一点,您的 API 上传端点可以处理 Oauth2.0 Bearer 令牌,但不依赖于它们。例如任何人都可以使用该端点,并且在标头中提供访问令牌的人将上传与 API 从令牌中获取的用户上下文相关联。 然后,如果需要,您可以使其他端点依赖于令牌。

基于 cmets 编辑

注册过程本身将使用客户端凭据授权, 对吗?

我认为注册过程本身不应该是受 Oauth 保护的资源。理想情况下,注册应由您的身份提供者(例如 google、facebook 或您自己的用户会员数据库)处理。 Oauth2.0 的优点之一是它不再需要 API 来执行用户管理工作。

【讨论】:

  • 您好,感谢您的回复。我的 API 将有一些不需要任何用户的端点(他们可以作为客人做事),所以在这种情况下,我认为客户端凭据授予可以完成这项工作。但是,当用户注册时(注册过程本身将使用客户端凭据授权,对吗?),那么显然相同的“访客”操作不能包含用户上下文。这部分让我有点困惑。我将如何解决这个问题?
  • 当令牌保存在 LocalStorage 中以供进一步的 Web API 请求时,如何使用密码授予处理令牌过期?
  • 密码授予会给你一个访问令牌。该令牌应包含有关发行/到期时间的详细信息,因此您可以计算它是否已过期或即将到期,并且您可以使用刷新令牌来获取新令牌。
  • 如果我没听错的话,我必须在客户端记住令牌何时到期并接近到期 调用我的 Web 应用程序,该应用程序存储了与用户相关的刷新令牌,并基于对于此刷新令牌,Web 应用程序从 OAuth 服务器请求一个新令牌,然后我的 Web 应用程序将新令牌发送回用户代理(浏览器)以进行进一步的 Web api 调用,对吗?
  • @Legends 我建议提出一个单独的问题,详细说明您的具体情况。通常,您的网络应用不会将令牌发送回浏览器,但需要更多细节才能给出正确答案。
【解决方案2】:

您实际上并不需要 oauth 来对您自己的 API 进行身份验证。

如果您希望其他应用程序访问您的 API,OAuth2 非常有用。

让我稍微解释一下 OAuth2 的工作原理:

  • 客户端(应用程序)想要使用您的 API,因此您向他提供客户端凭据(client_token 和 client_secret)。您在数据库中设置了一组客户端可以使用的重定向位置。
  • 客户端需要用户授权才能代表用户使用您的 API。因此,客户端将用户发送到您网站上的 url(使用 client_token,客户端需要的范围 [您定义不同范围的含义],重定向 uri 和 response_type [oauth2 定义了不同的 response_type,但让我们专注于'代码'])
  • 用户登录到您的站点并接受代表用户访问您的 API 的客户端。当用户接受这一点时,您将生成一个授权(授权包含用户的信息、请求的凭据 [范围] 以及可以“声明”授予访问权限的客户端)。
  • 然后用户被重定向到客户端请求的 redirect_uri(当客户端将用户发送到您的身份验证站点时),并且在 URL 参数中您将包含授权代码(它只是一个 id)。
  • 在这个阶段,客户端将向您的 API 发出请求,提供授权代码、他自己的 client_token、他的 client_secret 和 grant_type (authorization_code),他将得到以下响应:authorization_token、refresh_token、token_type (在这种情况下,Bearer)、expires_in(以秒为单位的过期时间)和范围。
  • 在此之后,客户端将能够代表用户使用 access_token 向您的 API 发出请求,直到令牌过期。令牌过期后,客户端将不得不使用 refresh_token(而不是授权码)请求新的 access_token。

【讨论】:

  • 我计划将来让我的用户在我的网络应用程序上注册应用程序,我知道 OAuth2 是处理这个问题的完美方式。所以考虑到这一点,我认为从一开始就使用 OAuth2 来验证我自己的应用程序会更明智,因为总有一天我会最终实现它。我的 API 将用 Laravel 编写,我不确定是否可以将多种身份验证方法附加到我的应用程序,所以我想在一开始就做出正确的选择,并长期坚持下去。
  • 如果您打算让用户在您的 WEB 上注册应用程序,那么您就在正确的轨道上。我以前从未使用过 Laravel,但我强烈建议您使用第三方库来实现 OAuth2,因为从服务器端实现它非常复杂。
【解决方案3】:

iandayman 的答案有很多很好的信息,但我认为更具体的答案可能会对您有所帮助。

所以对于初学者来说,客户端凭据授予不适合您。如果我们查看OAuth2 spec,客户端凭据授予是针对

当授权范围为 仅限于客户端控制下的受保护资源......当客户端代表自己行事时

这不适合您,原因有两个。
首先,您的客户控制下没有受保护的资源。您正在访问的所有资源要么未受保护(未登录的人上传),要么受最终用户的控制。此外,您不能在浏览器中保守秘密(例如客户端秘密);您的应用程序的任何用户都可以使用浏览器的开发人员工具来查看和泄露机密。
其次,正如我所提到的,客户从不代表自己行事。它始终代表可能登录或未登录的用户。

您希望授予资源所有者密码凭据
当用户未登录时(如您提到的上传),您没有授权。当用户登录时,您将他们的凭据发送到授权服务器。如果密码与用户名匹配,授权服务器会生成一个令牌,并保留从该令牌到用户的映射并返回该令牌。然后,每次您的客户端向已登录用户发出另一个请求时,您将该令牌放入 Authorization 标头中。在后端你说“如果授权标头中有一个令牌,找出它对应的用户,并将他们与这个上传相关联(或检查他们是否被允许上传)”。

用户注册如何运作?很简单,你发布一些用户对象,比如

name: jim beam
username: jimb
password: correct horse battery staple

到您的用户创建端点(POST /users 或其他东西)。您生成盐并对密码进行哈希处理,然后将用户信息与盐和哈希一起存储在数据库中。此端点上没有任何授权。

希望这是您正在寻找的更多内容。

【讨论】:

  • 完全没有授权安全吗?是否有任何潜在的滥用可能?我的问题可能听起来很荒谬和有趣,但我真的在问是否有什么可能出错的地方?注册端点的问题相同。
  • @Aborted 只有对未受保护的资源(任何人都可以做的事情)没有授权才是安全的。这些将是诸如 javascript 应用程序本身、公共配置文件、媒体等之类的东西。对于受保护的东西(私人图像、修改用户设置等),您将希望确保调用端点的人得到授权。不需要控制注册端点(假设任何人都可以注册)。您在这里的潜在问题是人们使用的公共资源超出您的处理能力。这些并不是严格意义上的安全问题,而是逻辑和扩展性问题。
  • 密码授权仅适用于您的应用,但您不会将此授权类型用于并非由您开发但使用您的 API 的应用。如果您计划公开您的 API,请查看其他授权类型以供他们使用。
  • @kag0 - 现在已经过去几年了,您认为 ROPC 仍然是一个不错的选择吗?例如,Identity Server 的主要开发人员之一的这篇文章:scottbrady91.com/OAuth/…
  • @anon 我几乎同意他在那篇文章中的所有内容。但在这种情况下,ROPC 仍然是正确的授权。需要了解的重要一点是 OAuth 是一种授权协议,但问题是如何将其应用于自己的应用程序上的身份验证。文章也提到了这一点,“如果您拥有授权服务器以及客户端应用程序,那么这是可以原谅的”。我还建议不规范并为用户帐户添加 FIDO/U2F/webauthn(这将确保只有您的客户端应用程序可以使用密码凭据)。
猜你喜欢
  • 2017-03-03
  • 2012-06-04
  • 2019-02-12
  • 1970-01-01
  • 2014-01-26
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多