当考虑OAuth2.x授权类型(例如代码或密码或隐式授权类型),最终,JavaScript web前端应用程序将获得JWT访问令牌作为对认证请求的响应(例如,登录用户)。
然后,前端会在后续发送给后端的请求的bearer header中使用上述access token(在其有效期内),这意味着这个access token需要存储在前端,以便在形成后续请求时使用请求header中的access token。我说的有道理吗?
我的两个问题:
Q1.将access token存放在JavaScript前端会不会不安全?因为浏览器的开发者工具可以揭开这个访问令牌,这可能会被恶意用户使用。我说的有道理吗?如果是这样的话,什么是正确的方式来托管这个 * 访问令牌 * 在前端一旦它得到它后,身份验证?
**Q2.**如果前端也想通过检查内部声明来验证令牌,这意味着前端需要公钥,这是一个好方法吗?如果没有,如果前端在形成对后端的后续请求时需要验证存储的令牌,那么更好的方法是什么?
3条答案
按热度按时间xfb7svmp1#
你第一个问题中的担忧实际上是有道理的,但不是你所说的原因。正如Evert已经提到的,最终用户只能访问他们自己的浏览器存储。但是,由于XSS攻击,在浏览器中存储访问令牌仍然有相当大的风险。这里有一些事实
1.当您将访问令牌存储在会话存储或本地存储中时,您需要检索令牌以供以后在API调用中使用
1.客户端存储 * 通常 * 容易受到跨站点脚本攻击。在这种情况下,任何 bad JavaScript代码,只要能够在与您的 *good * Javascript代码相同的浏览环境中运行,都可以访问存储的访问令牌。例如,这可能是通过恶意浏览器扩展或易受攻击的npm模块注入的代码,您正在使用该模块作为代码中的上游依赖项。
基于这些事实,在客户端存储令牌可能会导致令牌泄漏。您可以尝试通过编写适当的内容安全策略(CSP)来限制XSS的潜力,但风险仍然存在。因此,如果您的应用程序 * 必须 * 在客户端存储令牌,您应该:
1.将令牌存储在会话存储(而不是本地存储)中,以限制仅对当前选项卡或会话公开
1.将令牌存储在服务工作线程中,这更安全,因为工作线程在具有隔离存储的单独线程中运行。但这在状态管理方面要棘手得多,因为不能保证服务工作者将持续运行。
话虽如此,OAuth工作组建议在服务器端存储令牌,假设单页应用程序(SPA)具有相应的后端。下面是它的工作方式:
1.用户单击“LoginwithGoogle”(为简单起见,假设是Google,但它可以是任何其他IDP)并被重定向到后端端点
/api/oauth/google
。后端作为机密客户端启动OAuth或OIDC流,检索ID和访问令牌。1.这些令牌经过验证,存储在服务器端(内存中,关系数据库或Redis等键值存储),并通过返回到前端的会话ID链接到客户端。
1.使用会话ID cookie将用户重定向回前端
这就是Backend For Frontend(BFF)模式。作为前端和后端之间的代理,或者作为后端本身。在这种情况下,前端避免处理身份验证/授权,向后端发送请求,后端也会自动发送会话cookie。后端处理其余的。
解决您的第二个问题,虽然前端可以从技术上获得授权服务器(AS)的公钥来验证令牌,但通常没有必要。OAuth令牌对客户端来说是“不透明的”--客户端只需要将令牌作为授权头附加,而不需要理解其内容。令牌验证和授权决策是资源服务器的职责。如果前端需要用户配置文件数据,则可以使用访问令牌调用AS的
/userinfo
端点,或者在资源服务器中创建自定义/userinfo
或/me
端点。bn31dyow2#
在JavaScript前端存储访问令牌是不是不安全?因为浏览器的开发者工具可以公开此访问令牌,这可能被恶意用户使用。我说的有道理吗?如果是这样的话,什么是正确的方式来托管这个访问令牌在前端,一旦它得到它后,身份验证?
用户只能访问自己的令牌,而不能访问其他人的令牌。不应该有用户访问自己的令牌是安全风险的情况。
Q2.如果前端也想通过检查内部的声明来验证令牌,这意味着前端需要公钥,这是一个好的方法吗?如果没有,如果前端在形成对后端的后续请求时需要验证存储的令牌,那么更好的方法是什么?
是的,在任何地方使用公钥都没有错。它们是公开的。
您可能也对本文档感兴趣:
https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-14.html
这将是一个RFC,并有许多关于基于浏览器的应用程序的建议。
um6iljoc3#
我不使用OAuth,但我使用JWT,令牌在前端做的唯一事情就是显示用户的基本信息,这些信息与授权等事情无关。我不建议在前端验证令牌,因为你用来创建令牌的签名大多数都在前端,这是一个很大的安全问题。所以根据我的经验回答你的问题:
1.如果您不使用密码、凭据等信息来创建令牌,则不需要。
1.你可以从前端验证token,但你不应该,在后端使用中间件,这样你就可以验证token,你可以解码token搜索用户,如果你不想在token中使用角色或用户类型,你可以带来信息,然后你决定用它做什么操作,如果你让它传递给路由,或者不,这是一个示例,但使用简单的中间件,您可以以不同的方式验证令牌
我希望我说得很清楚,让我知道如果你有任何其他问题或澄清的东西。