关于身份验证后访问令牌前端获取的问题

use*_*225 4 authentication frontend oauth access-token oauth-2.0

当考虑 OAuth2.x 授权类型(例如代码或密码或隐式授权类型)时,最终,javascript Web 前端应用程序将获得 JWT访问令牌作为身份验证请求(例如登录用户)的响应。

然后,前端将在发送到后端的后续请求的承载标头中使用上述访问令牌(在其有效期内),这意味着该访问令牌需要存储在前端侧,以便在形成后续请求时在请求标头中使用访问令牌。我在这里说得通吗?

我的两个问题:

Q1. 将访问令牌存储在 javascript 前端不是不安全吗?因为浏览器的开发人员工具可以公开此访问令牌,该令牌可能被恶意用户使用。我在这里说得通吗?如果是这样,在身份验证后获得此访问令牌后,在前端托管此访问令牌的正确方法是什么?

Q2。如果前端还想通过检查内部声明来验证令牌,则意味着前端需要公钥,这是一个好的方法吗?如果不是,如果前端在向后端形成后续请求时需要验证存储的令牌,那么更好的方法是什么?

ade*_*del 6

你第一个问题中的担忧实际上是有道理的,但不是出于你所说的原因。正如埃弗特已经提到的,最终用户只能访问他们自己的浏览器存储。然而,由于 XSS 攻击,在浏览器中存储访问令牌仍然存在相当大的风险。这是一些事实

  1. Oauth 2.0 访问令牌是不记名令牌,这意味着令牌本身与其用途之间没有任何绑定。也就是说,任何拥有该令牌的人都可以使用它。
  2. 当您将访问令牌存储在会话存储或本地存储中时,您需要检索令牌以供以后在 API 调用中使用
  3. 客户端存储通常容易受到跨站点脚本的攻击。在这种情况下,任何不良的JavaScript 代码如果能够在与良好的Javascript 代码相同的浏览上下文中运行,也可以访问存储的访问令牌。例如,这可能是通过恶意浏览器扩展或您在代码中用作上游依赖项的易受攻击的 npm 模块注入的代码。

基于这些事实,在客户端存储令牌可能会导致令牌泄露。您可以尝试通过编写适当的内容安全策略 (CSP) 来限制XSS 的可能性,但风险仍然存在。因此,如果您的应用程序必须在客户端存储令牌,您应该:

  1. 将令牌存储在会话存储(而不是本地存储)中,以限制仅暴露于当前选项卡或会话
  2. 将令牌存储在服务工作人员中,这更安全,因为工作人员在具有隔离存储的单独线程中运行。但这在状态管理方面要棘手得多,因为无法保证 Service Worker 会持续运行。

话虽这么说,OAuth 工作组建议在服务器端存储令牌,假设单页应用程序 (SPA) 具有相应的后端。这是它的工作原理:

  1. 用户单击“使用 Google 登录”(为简单起见,假定为 Google,但它可以是任何其他 IDP)并被重定向到后端端点/api/oauth/google。后端作为机密客户端启动 OAuth 或 OIDC 流,检索 ID 和访问令牌。

  2. 这些令牌经过验证,存储在服务器端(内存中、关系数据库或 Redis 等键值存储),并通过返回到前端的会话 ID 链接到客户端。

  3. 使用会话 ID cookie 将用户重定向回前端

这是后端用于前端 (BFF) 模式。充当前端和后端之间的代理,或者作为后端本身。在这种情况下,前端避免处理身份验证/授权,将请求发送到后端,后端也会自动发送会话 cookie。后端处理其余的事情。

解决第二个问题,虽然前端在技术上可以获取授权服务器(AS)的公钥来验证令牌,但通常没有必要。OAuth 令牌对客户端来说是“不透明的”——客户端只需将令牌附加为授权标头,无需了解其内容。令牌验证和授权决策是资源服务器的职责。如果您的前端需要用户配置文件数据,您可以使用访问令牌来调用 AS 的端点或在资源服务器中/userinfo创建自定义端点/userinfo或端点。/me