paint-brush
帮助!我的元宇宙中有一个 JWT!经过@patrickleet
1,709 讀數
1,709 讀數

帮助!我的元宇宙中有一个 JWT!

经过 Patrick Lee Scott8m2022/07/25
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

Web3 的出现和钱包的广泛使用将导致用户放弃传统的基于电子邮件/密码的帐户系统,转而使用他们的钱包登录。 JWT 虽然起初有点令人困惑,但对后端工程师来说非常有用,尤其是微服务系统的工程师。 “screw-JWT”人群建议使用简单的 Session ID,但这与 2000 年代初期相比是倒退了一步,当时简单的分层架构是标准,没有当今后端系统的复杂性。 Patrick Lee Scott 探索在 web3 世界中使用 JWT。

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - 帮助!我的元宇宙中有一个 JWT!
Patrick Lee Scott HackerNoon profile picture

JWT 真的死了,还是只是被误解了?

我最近看到不少文章暗示 Web3 的出现和钱包的广泛使用将导致用户放弃传统的基于电子邮件/密码的帐户系统,转而使用他们的钱包登录。


说实话,在使用了几个 dApp 之后,你的钱包一两下弹出的超级简单的工作流程确实是一种超凡的体验。


其中许多文章继续说“是的,我们不再需要 JWT!”。


这是我不同意的地方。


JWT 虽然起初有点令人困惑,但对后端工程师来说非常有用,尤其是微服务系统的工程师。特别是考虑到这些系统(其中很多)已经存在并且已经与 JWT 集成!以太坊很棒,但我们真的不需要重新发明轮子。能够在需要时继续使用您习惯的相同后端工具是一件好事。


使用 MetaMask 登录证明是你——但你如何向未来的 API 调用证明是你?


“screw-JWT”人群建议使用简单的会话 ID,但请注意,这是对 2000 年代初期的倒退,当时简单的分层架构是标准,没有当今后端系统的复杂性。


不幸的是,如果不额外往返数据库以确定授予的会话 ID 是否属于有效会话,则无法验证会话 ID。这意味着当后端服务接收到包含会话 ID 的请求时,它会自己向身份验证服务器发出请求,询问“这个是否处于活动状态”——然后微服务系统中的所有其他服务都会询问相同的问题。


如果涉及多项服务,则可能需要多次往返身份验证服务。


为了纠正这种情况,密码学专家开始思考。


他们想出的是 JWT——现在是 OpenID 标准的一部分,你知道,Keycloak、Auth0 和其他人帮助你实现的标准。

JWT,你们大家

解决方案是授予一组令牌 - 准确地说是 JSON Web 令牌。该集合由AccessTokenRefreshTokenIdToken 。然后这些令牌由一个秘密“签名” - 通常称为ClientSecret 。签名,就像我们在同一页面上一样,是一种加密哈希算法,在 JWT 的情况下——通常是HS256 (Auth0 的默认值)。在HS256的情况下, ClientSecret被用作输入,因此成为成功破译该哈希或“验证”它所需的密钥。对于RS256ES256 ,使用公钥/私钥对,即由私钥签名,并在客户端使用公钥进行验证。


这意味着如果后端服务接收到这些令牌之一,并且它知道ClientSecret ,它可以验证令牌实际上是由签署该令牌的身份验证服务颁发的。尝试访问后端服务时使用的令牌是AccessToken 。这些令牌特别包含有关用户是谁以及他们的“声明”的信息,或者换句话说,他们被允许为关心它的系统进行格式化的操作。


对于微服务系统,这意味着每个关心验证身份的服务只需要了解ClientSecret ,因为他们可以使用它来验证 JWT 的真实性,而不是往返数据库。在具有许多微服务的系统中,这可以减少许多额外的数据库往返,使整个系统更具可扩展性。


访问令牌如果被盗,可能会被恶意使用,因此,在设计使用它们的系统时采取适当的预防措施非常重要。


除了签名和验证令牌之外,最低限度的预防措施包括:


  1. 将访问令牌 JWT 的到期日期设置为 5-15 分钟,并确保收到令牌时不会过期

  2. 不要将访问令牌存储在内存中

  3. 发出刷新令牌,可以存储并发送到服务器进行验证,并使用发出它的ClientSecretClientId刷新。

  4. 仅在通过 TLS 连接 (HTTPS) 传输时使用

  5. 使用仅 HTTP cookie,因此它们不能在浏览器端进行修改

  6. CORS 设置

  7. 此算法必须使用与散列输出大小相同的密钥(例如,“HS256”为 256 位)或更大的密钥。 - RFC7518 ,注意: Auth0 对 HS256 使用 512位。


机密客户端需要一个中间服务器,例如 Node.js - 该服务器是身份验证服务的代理,因此客户端不需要知道客户端机密。公共客户端公开客户端机密,并且浏览器和身份验证服务之间没有代理服务器。这可以通过 CORS 设置进一步限制,因此只允许来自某些域的请求。


其他预防措施包括:


  1. 使用轮换刷新令牌——每个令牌只能使用一次。使用时,它会换成一组全新的令牌,并且交换的刷新令牌会被撤销。如果采用此策略,值得注意的是,互联网连接不佳的用户有时无法收到对刷新请求的响应并重试。出于这个原因,30 秒左右的短暂宽限期将允许他们点击刷新并重试。
  2. 允许用户通过注销来撤销所有现有的刷新令牌。


可能还有更多——例如,如果您检测到有人试图使用已撤销的刷新令牌,您可以撤销该用户的所有活动刷新令牌。


诚然,所有这些预防措施都会使正确处理变得有点困难。有很多要理解的。还有可用性问题。用户每 5 分钟从您的网站注销一次,他们会觉得很烦人。为避免这种情况,必须在消费应用程序中实现静默刷新循环以不断刷新令牌集。


也就是说,另一方面,它能够以可扩展的方式安全地与您的所有后端系统以及许多现有工具集成 - 例如Hasura ,它可以根据您自动生成所有 API一个连接的 Postgres 的数据库模式。因此,能够与现有工具轻松集成可以节省大量开发时间。


如果您已经使用 OpenId,很可能您已经准备好这些东西。毕竟,它是一种身份验证标准。


那么我们如何才能保持在 Web3 中使用 JWT 并使用 MetaMask 世界登录的便利性呢?

JWT 和 Web3?

让我们首先了解用于 SSO 的 OpenId 身份验证流程。


  1. 您访问一个网站并希望使用您的帐户登录 - 您单击登录按钮
  2. 您被重定向到 SSO 登录页面 - 您使用电子邮件/用户名和密码登录
  3. 您将被重定向回原始应用程序,其中包含一组适当存储并用于静默刷新后台流的 JWT。


在 web3auth 世界中,我们将第二步替换为使用您钱包的私钥和公钥对来签署挑战。不需要或不需要重定向。


  1. 您访问一个网站并希望使用您的帐户登录 - 您单击登录按钮

  2. 你会收到来自身份验证服务器的挑战,它会打开你的钱包,要求你“签署”挑战。按标志。

  3. 身份验证服务器验证您的签名并向您发出一组 JWT,这些 JWT 被适当地存储并用于静默刷新后台流程。



我们只是将 SSO 样式重定向流程替换为由您的钱包签名的挑战。收到令牌后的流程与 OpenID 相同。这意味着您可以例如从使用 OpenID 切换到使用带有 JWT 发布服务器的 web3auth,并且在授予这些令牌后无需更改任何关于使用这些令牌的事情。您与 Hasura 等工具的所有现有后端集成都保持不变。


这正是我作为全周期开发人员想要的。我不想重新发明轮子。我想用 web3auth 替换 OpenID,并且仍然能够使用我习惯的所有强大工具。


不幸的是,我找不到执行此操作的 web3auth 服务器以及安全预防措施。我发现一些项目在这个过程中展示了技术,但不是端到端的整个流程。


所以我开始建造……


我在这里构建了这个身份验证服务器: https ://github.com/CloudNativeEntrepreneur/web3auth-service


而这里的 SvelteKit集成与之配套,实现了所有的东西 - 静默刷新,yada yada - 我上面提到的所有这些东西: https ://github.com/CloudNativeEntrepreneur/sveltekit-web3auth


当然,如果有 GraphQL 客户端和示例,那么还需要有 GraphQL 服务器和数据库,所以我还提供了示例: https ://github.com/CloudNativeEntrepreneur/example-hasura + https: //github.com/CloudNativeEntrepreneur/example-readmodel


此示例使用Zalando Postgres 运算符SchemaHero ,因此您只需声明您的数据库并在 YAML 中描述您的模式,Hasura 将自动生成您需要的所有 GraphQL API。而且,我在考虑 Hasura 的情况下制作了身份验证服务器,因此它具有与 Hasura 的 RBAC 和权限集成的正确声明,这些都非常强大。


当然,您需要一个地方来运行所有这些,因此,需要一个本地开发集群来为您设置所有工具,如 istio、操作员和 SchemaHero! https://github.com/CloudNativeEntrepreneur/local-dev-cluster


但是谁知道如何使用这一切呢?


所以这就是我制作这个回购的原因: https ://github.com/CloudNativeEntrepreneur/web3auth-meta


使用该元存储库会将您需要的所有项目克隆到正确的位置,并一起运行它们。


最后,要一起运行所有项目,您需要安装工具,而安装工具很烦人 - 所以我在这里制作了这个 repo,它将为您安装它们! https://github.com/CloudNativeEntrepreneur/onboard


我还在 npm 上发布了sveltekit-web3auth ,并从一个使用它的 SvelteKit 项目中制作了一个模板,并设置了 GraphQL 并将其与 Hasura 实例的身份验证集成,因此当你准备好制作自己的项目时,你可以使用它作为模板! https://github.com/CloudNativeEntrepreneur/sveltekit-web3auth-template


如果您还没有为 web3 auth 世界做好准备,您还可以使用https://github.com/CloudNativeEntrepreneur/sveltekit-oidc ,它预先配置为连接到您的本地开发集群,以及在其中设置的 Keycloak 实例它。从两个项目如何发布 JWT 来看,目标是使身份验证系统可互换 - 使用 web3auth 或经典 OIDC - 令牌的上游使用是相同的。


现在开始使用自动生成的 GraphQL API 和强大的 RBAC 以及权限和订阅以及经过身份验证的 SSR 页面以及静默刷新循环和旋转刷新令牌等东西来制作一些混合 dApp!

结论

总之,不,JWT 和使用以太坊/元掩码登录并不是相互排斥的。事实上,如果您喜欢开发人员的生产力并与现有工具集成,我认为使用 JWT 和 web3auth 会做得很好。


干杯!


我可以咨询!如果您对我对您正在进行的项目的帮助感兴趣,请在 Twitter 上给我发送消息!