【问题标题】:Authorization Code Grant: is it safe to send the tokens to the client?授权码授予:将令牌发送给客户端是否安全?
【发布时间】:2021-02-20 04:26:39
【问题描述】:

假设我在同一个域上有一个带有后端的 SPA。如果我必须连接到外部 OAuth 提供者(比如说 Google),授权代码流(没有 PKCE)是更安全的选择。这意味着:

  • SPA 向授权服务器请求code
  • 然后,它将code 发送到后端
  • 后端与 AS 交换code(和一个秘密)以获得tokens
  • 后端通过 SPA 设置 Session Cookie 以保持用户登录

此流程是最安全的,因为 SPA 从不会看到单个令牌。它不使用它们。如果我必须使用访问令牌向 API 发出请求,SPA 将向后端发出请求,后端将使用访问令牌来获取资源。并且后端还负责使用 Refresh Token。到目前为止一切顺利。

现在,如果后端在成功交换后(一旦获得令牌)将令牌发送回浏览器会怎样?这样,客户端就可以自行访问 API 的端点。

理论上,如果我没记错的话,应该避免这种情况。将代币还给前端有点违背授权代码授予的目的,您不妨使用带 PKCE 的授权代码直接在前端获取代币,对吧?使用 Code Grant,获得身份验证的是后端,而不是 SPA。

但我在想:这就是 Firebase 的作用,不是吗?据我所知,Firebase 使用授权代码(没有 PKCE),重定向到 Firebase 应用程序的后端 (__auth/handler),然后 它仍然将令牌提供给前端- end(id 令牌、访问令牌、刷新令牌)。

我错过了什么吗?还是在授权码授予结束的时候把token给前端就可以了?

PS。显然,在 Firebase 的情况下,后端实际上不会使用这些令牌,它依赖于我想象的每个请求中发送的浏览器令牌。在我提到的情况下,后端存储这些令牌,所以理论上我将有两组令牌:后端通过代码交换接收的令牌,以及发送到浏览器的令牌(最初它们是相同的,但在第一次刷新后它们是不同的)。后端是否应该完全丢弃令牌并依赖浏览器的令牌?我认为应该是这样,因为如果启用了 Refresh Token Rotation,则在浏览器第一次刷新后后端将有一个无效的 Refresh Token。这种情况快把我逼疯了。我的观点是令牌应该保留在后端,但我试图弄清楚 Firebase 方法如何安全。

【问题讨论】:

    标签: firebase oauth-2.0 firebase-authentication openid-connect


    【解决方案1】:

    很有趣不是吗?需要权衡取舍,不同的技术对如何使用代币做出不同的选择。

    简短回答

    如果在浏览器中使用访问令牌本身并不是不安全的。通常建议保持令牌的短暂性、机密性并仅将它们存储在内存中。

    是否使用这样的代币还可能取决于数据敏感性和利益相关者的意见。

    大图

    我们真正希望这两种技术能够以等效的技术方式工作。毕竟,两者通常都需要做同样的工作,即调用 API 来访问数据,然后向用户展示屏幕。

    • 网页界面
    • 移动用户界面

    在移动 UI 中使用访问令牌是完全标准的,但有些人担心在 Web UI 中这样做。

    网页界面

    如您所描述的,一种选择是将令牌保留在浏览器之外并使用“网络后端”。从安全角度来看,许多人更喜欢这种方式,但与纯 SPA 架构相比,它有以下缺点:

    • 您必须通过 Web 后端对 API 的所有调用进行双跳,效率较低
    • 需要运行代码以发出身份验证 cookie 的 Web 后端可能会导致托管不理想,您无法使用内容交付网络部署 Web 资源
    • 由于两种形式的后端凭据:网络 cookie 和移动令牌,还存在其他复杂性

    2021 年的所有权证明?

    希望这些对于公共客户端来说并不遥远——DPoP 令牌可以在 Web UI 和 API 之间发送。这意味着从浏览器窃取的访问令牌无法重放,并将进一步减少对 Web 后端的需求:

    浏览器威胁

    当然,浏览器的安全性不仅仅局限于 cookie 和令牌,而安全性是关于覆盖风险的。值得考虑一下您所关心的威胁以及如何缓解它们 - 这篇博文中有一些注释,说明我是如何为我的在线代码示例推断出这一点的:

    【讨论】:

    • 你所说的访问令牌是真的,但“Firebase 方法”困扰我的是浏览器也获取刷新令牌并将其存储在 indexedDB 中。所以:它不是短暂的,它不是安全存储的,不再是机密的。但是,很明显为什么需要这种方法:如果浏览器只有一个访问令牌,一旦过期它会做什么?它必须重新向用户请求许可,这是一个非常糟糕的用户体验。如果授权服务器在同一个域上,您可以执行静默更新,好的,但如果不是这样呢?对我来说似乎有风险!
    • 关于您提到的缺点:1)我同意,双跳效率较低(但更安全),2)您可以使用非集中式 Redis 服务器而不是 Sticky Sessions,以防您的应用程序在增长,您需要一个负载均衡器,3) 我不是移动专家,但您不能在移动设备上使用相同的机制使用 Cookies 吗?如果没有,我认为如果您的公司或项目足够大,可以拥有移动设备,那么实施 2 种策略应该不是问题 :) 所以我同意这些都是缺点,但可以解决!
    • 我同意你对刷新令牌的看法——我总是避免将它们存储在浏览器中,或者在浏览器中使用本地存储令牌。授权服务器将发布自己的会话 cookie,如果需要,可用于更新访问令牌 - 或者您可以在应用程序中执行此操作...
    猜你喜欢
    • 2017-10-18
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2020-11-22
    • 1970-01-01
    • 2021-01-28
    相关资源
    最近更新 更多