我可以将授权代码授予与 API(我拥有的)紧密耦合的 SPA 吗?

Can I use Authorization Code grants for an SPA tightly coupled with an API (that I own)?

我正在构建一个只与一个后端通信的 Angular(版本 5)应用程序,即我的 API(Web 服务器上的 Flask 应用程序),后者又与我的数据库通信。该应用程序用于数据输入和可视化,其中数据不断加载并保存 to/from 后端。我控制了所有三个部分。

我正在考虑使用 Auth0 来处理 auth/user 管理。

我的问题是,我能否将此应用程序视为 'regular' 网络应用程序并使用身份验证代码授权,而不是通常建议用于 SPA 的隐式授权?即:

  1. SPA 将通过重定向到适当的 auth0 页面的 /login 端点从 auth0 获得授权代码
  2. 授权码通过某个端点(可能是 /callback 端点)传递给 API。
  3. API 与 Auth0 对话以交换 AC 以换取令牌。
  4. 令牌随每个请求传递到数据库,如果令牌无效则拒绝(可以使用 postgresql 在数据库中检查令牌有效性)
  5. API 服务器上的令牌与用户之间的关联是通过加密的 cookie 完成的(Flask 的 'session' 变量)

通读了很多关于隐式授权与身份验证代码授权的讨论,主要区别似乎是在真正的 SPA 应用程序中,没有由资源提供者控制的可以存储客户端秘密的单一服务器或令牌。但是,根据我的情况,我不能只将 SPA 应用程序视为传统的(ajax-重)网页吗?

我在 auth0 论坛上发现了这个post,它暗示这可能“很脆弱,因为在实践中你有一个 OAuth2 流被应该是两个独立的组件处理”,但我不明白如何组件之间的独立性应该有所不同。

是的,您可以使用授权码。如果你使用它,会有一些设计影响:

  • 您的后端将扮演 OAuth2 客户端的角色,而不是 SPA
  • 如果您将令牌从后端传递到您的 SPA 并将其用于身份验证(如果这就是您问题中第 4 点的意思),令牌将在一段时间后过期,用户将不得不离开再次通过身份验证过程,这可能很烦人。

所以我建议:

  • 要执行身份验证,后端应该有两个端点 - 一个用于重定向到 OAuth2 服务器,一个用于接受来自 OAuth2 服务器的重定向(包含授权代码)。无需将代码获取到您的 SPA。
  • 后端交换令牌的代码。如果需要,可以将令牌保存在后端会话中,或者只将用户信息保存在会话中——您可能不再需要这些令牌。

因此,使用这两种授权之间的主要区别在于,使用隐式授权,您的 SPA 需要能够在过期前更新令牌(请参阅 OpenID Connect Session Management),并且使用身份验证代码授权,后端需要有状态 - 为其客户端保持会话。