在授权代码授予流程中,一旦单页应用程序 (SPA) 等公共客户端获得 OAuth 2.0 访问令牌,SPA 应该将其保存在哪里?
因此,我看到的唯一安全的剩余选项是将其保留在内存中。它真的安全吗?这是唯一安全的方法吗?
这完全取决于您愿意接受的风险。
如果您将其存储在 cookie 中,您可能会向 CSRF 开放您的应用程序。虽然通过将令牌存储在 httponly cookie 中来将 XSS 换成 CSRF 可能有意义,但使用非 httponly cookie 这样做没有多大意义,因为除了 CSRF 之外,它还容易受到 XSS 的攻击。
很多情况下将其存储在 localStorage 或 sessionStorage 中就可以了。选择该选项后,您就接受了 XSS 访问令牌的风险。为了减轻这种风险,您可能需要实施缓解措施,例如使用合适的工具进行静态安全扫描、定期渗透测试等 - 安全不仅仅是代码,它还包括围绕如何创建代码的过程。缓解措施到位后,您可以决定接受残余风险。您还可以将令牌存储在内存中,例如我猜在 IIFE 中,从那里在 XSS 攻击中读取起来有些困难。将其存储在普通变量中并没有帮助(来自 XSS 的 javascript 仍然可以访问),而且我不完全确定最新的 JS 可以做什么来安全地使其无法从给定对象外部访问。这可能不可能以真正安全的方式实现。
或者您可以走另一条路。您可以在 localStorage 中存储非常短暂的访问令牌,并接受 XSS 访问的风险。但是,您的 IdP 可以在 IdP 域的 httponly cookie 中发出刷新令牌。这样,即使访问令牌被泄露,它也仅在有限的时间内有效,然后攻击者将无法更新它。这在某些应用程序中可能有意义,但在其他应用程序中可能没有意义。
RFC6749 (old skool) 中描述的授权码
不要使用此客户端,请使用Auth Code + PKCE。
RFC6749 (https://datatracker.ietf.org/doc/html/rfc6749) 中描述的授权授予流程。在此“流程”中,客户端向授权服务器发送代码请求,服务器用代码进行响应,客户端用代码交换令牌。 (不要在客户端使用这个,仅使用服务器端)
最近,这是网络应用程序的首选解决方案。趋势是创建一个机密客户端并在服务器端进行代码 <> 令牌交换。 (https://datatracker.ietf.org/doc/html/rfc6749#section-2.3)。这样,只有被委托了 client_secret 的计算机才能获得令牌。
Auth Code 需要在服务器端存储访问令牌。(注意:此流程也用于移动应用程序,但这是它自己的主题......)
授权码 + PKCE(公共客户端),如 RFC7636 中所述
第二种类型的“流”是带有 PKCE(公共客户端)的授权代码,如 RFC 7636 (https://datatracker.ietf.org/doc/html/rfc7636) 中所述。此流程设计用于在客户端使用。在这种情况下,客户端生成一个密码(也称为代码验证程序)并将其包含在向授权服务器发出的代码请求中。服务器响应一个代码,客户端用代码+密码交换令牌。
对于“流程#2”(公共客户),需要考虑一个重要风险。对于Code + PKCE Public Client,不限制哪台计算机可以发起身份验证请求或接收令牌。这意味着,如果攻击者有办法获取代码验证者和代码,并且如果攻击者成功,则攻击者能够将其交换为令牌。如果这对您来说是可以接受的风险,或者如果这种风险得到缓解,请考虑 Gabor 提到的注意事项,将代币存储在 SPA 中希望这有帮助吗?