为 Web 应用使用自己的 API - 使用 OAuth2 的身份验证过程

Consuming own API for web app - Authentication process with OAuth2

概览

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

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


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

我知道 OAuth2 是 API 身份验证的方式,所以我要实现这个,但我真的很难思考如何处理我的情况。我考虑过使用 client credentials 授权并为我的 Web 应用程序生成 只有一组 凭据,并让它使用 [=12] 向 API 发送请求=] 获取访问令牌并让用户执行操作。用户注册过程本身将由这笔赠款处理。

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


我需要什么帮助

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

您的方法似乎可行。

Oauth2 有 4 个主要部分:

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

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

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

的上下文中给你一个令牌和刷新令牌

授权服务器中的 Authorization code grant is fine providing your future API consumers are web apps (i.e. run on servers). If you plan to allow mobile/native apps to use your API then you should consider allowing the Implicit 授予。

如果您的 API 没有最终用户,并且每个客户端对 API 的访问权限因应用程序而异,那么您可以使用 client-credentials 授权和使用 scopes 限制 API 访问。

编辑

So my API must be accessible to the world with guest access (non logged in people can upload, for example) and to registered users. So when a registered user uploads, I obviously want the user to be sent along with the request and attach that user to the uploaded image

为此,您的 API 上传端点可以处理 Oauth2.0 Bearer 令牌,但不依赖于它们。例如任何人都可以使用该端点,那些在 headers 中提供访问令牌的人的上传内容将与 API 从令牌中获取的用户上下文相关联。 然后,如果需要,您可以使其他端点依赖于令牌。

根据评论编辑

the registration process itself will use the client credentials grant, correct?

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

你真的不需要 oauth 来验证你自己的 API。

如果您希望其他应用程序访问您的 API。

,OAuth2 很有用

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

  • 一个客户(应用程序)想要使用您的 API,因此您向他提供了客户凭据(client_token 和 client_secret)。并且您在数据库中设置了一组客户端可以使用的重定向位置。
  • 客户需要用户授权才能代表用户使用您的API。因此,客户端将用户发送到您网站上的 url(具有 client_token,客户端需要的范围 [您定义不同范围的含义],重定向 uri 和 response_type [oauth2 定义不同 response_type 但让我们关注 'code'])
  • 用户登录到您的站点并代表用户同意向您的 API 授予对客户端的访问权限。当用户接受时,您将生成一个授权(授权包含用户信息、请求的凭据 [范围] 以及可以 'claim' 授予访问权限的客户端)。
  • 然后用户被重定向到客户端请求的 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。

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

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

when the authorization scope is limited to the protected resources under the control of the client ... when the client is acting on its own behalf

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

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

用户注册如何进行?很简单,你 post 一些用户 object 喜欢

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

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

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