@effected/jwt

中文文档
0.10.0发布于 2026/11/10MITTypeScriptES Module构建来源已验证近 30 天下载 1万

JWS,JWT,JWK和JWKS在WebCrypto上签名并验证Effect v4,工人安全.

中文使用文档
文档目录10 节
  1. 为什么 @ effect/jwt
  2. 安装
  3. 提供什么
  4. 签署 JWT
  5. 对照发行人公布的密钥校验
  6. 用您持有的密钥校验
  7. 算法
  8. 错误
  9. 测试
  10. 许可证

@ e受影响/ jwt

npm License: MIT Node.js %3E%3D24.11.0

签名和验证 JWTs for Effect v4,并从发行商已公布的密钥集中解析校验密钥. 一层薄的地层 effect/jose,它运行每个签名、密钥导入和权利要求检查,所以它在WebCrypto的任何地方都有效:Node、Bun、Deno、浏览器和Cloudflare工人,没有 node: 导入.

预1.0.0。 。 。 . 此软件包是 @effected/* 工具箱,在 稳定效果 v4并仍在 0.x 发展。 为了保持你的 effect 财务报告和审定财务报表 @effect/* 该工具包在线上构建和测试、安装 @effected/pnpm-plugin-effected。 。 。 .

稳定:不稳定. 此软件包的 API 表面尚未考虑 完成并可能改变 0.x 释放 准确的版本。 满 政策: 释放策略。 。 。 .

为什么 @ effect/jwt

核心 effect/jose 已签名并验证 JWS 和 JWT, 导入 JWK 并获取密钥集 。 当您对照您已经持有的密钥或一个固定的HTTPS JWKS URL进行校验时直接使用它(Jwks.layerRemote,用 PKCS#8 键签名,或需要 HMAC 或 JWE .

当您需要核心留给您时,请联系这个包:

  • OIDC发现的钥匙. JwksResolver 找到每个发行人的密钥集 <issuer>/.well-known/openid-configuration,检查发现文件名称 准确的发布者,服务于许多发布者 从一个服务 kid。 。 。 .
  • 你选择的缓存 . 获取的密钥集以 JwksStore: 与 JwksStore.layerMemory,或者在工人KV中, 所以每一个孤立者共享一个获取.
  • PEMs的人确实有. JwtKey.fromPkcs8Pem 使用 PKCS# 8 和 PKCS# 1 ()BEGIN RSA PRIVATE KEY,格式 github.com 将App 键输出出去),包括一条新行到达的键作为逃出 \n 在一行环境变量中.
  • 更安全的违约. Jwt.verify 允许 60 秒时钟 skew, 需要 exp 除非你们选择退出,并且拒绝将来发行的标志。 Core的默认值为零 skew 和可选 exp。 。 。 .
  • 一个路径错误 . 每一次失败都是 JwtError 有个公寓 reason 绳子.
  • 试发会. TestIssuer 标志通过真正的解析器进行验证,没有网络.

钥匙是核心本身的类型,所以是来自 JwtKey 也与核心协作 Jws 财务报告和审定财务报表 Jwt 直接说.

安装

npm install @effected/jwt effect
pnpm add @effected/jwt effect

在节点上,它需要Node.js QQ24.11.0;它还运行在任何其他WebCrypto运行时间上,Cloudflare Workers也包括在内. effect v4是唯一的对等器. 全体 @effected/* 软件包仅限无害环境管理.

提供什么

在您程序边缘提供的核心服务上签名和验证运行 :

运行要求数
Jws.sign, (中文(简体) ), Jws.verify, (中文(简体) ), Jwt.sign, (中文(简体) ), Jwt.verify, (中文(简体) ), JwtKey.generate, (中文(简体) ), TestIssuerSignature.Signature
JwksResolver.layer, (中文(简体) ), JwksResolver.layerWithHttpClient.HttpClient 财务报告和审定财务报表 JwksStore
Jwt.verify 键 JwksResolver.forIssuerSignature.Signature 财务报告和审定财务报表 JwksResolver

JwtKey.fromPkcs8Pem, (中文(简体) ), JwtKey.fromJwk 财务报告和审定财务报表 Jws.decodeUnverified 不需要任何东西.

服务任何 WebCrypto 运行时间( 包括工人)节点
Signature.SignatureSignature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto)) 从 effect/cryptoNodeCrypto.layerSignature 从 @effect/platform-node
HttpClient.HttpClientFetchHttpClient.layer 从 effect/httpNodeHttpClient.layerUndici 从 @effect/platform-node,或 FetchHttpClient.layer
JwksStoreJwksStore.layerMemory,或您自己的 KV 备份层JwksStore.layerMemory
import { JwksResolver, JwksStore } from "@effected/jwt";
import { Layer } from "effect";
import { SecureRandom, Signature } from "effect/crypto";
import { FetchHttpClient } from "effect/http";

const CryptoLive = Signature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto));

const JwtLive = Layer.merge(
  JwksResolver.layer.pipe(Layer.provide(Layer.merge(FetchHttpClient.layer, JwksStore.layerMemory))),
  CryptoLive,
);

签署 JWT

来自 PKCS# 1 关键 github.com 的 GitHub App JWT 问题. 标题是 {"alg":"RS256","typ":"JWT"}数字 : alg 总是来自钥匙.

import { Jwt, JwtKey } from "@effected/jwt";
import { Effect, Redacted } from "effect";

const signAppJwt = (pem: Redacted.Redacted<string>, appId: string, nowSeconds: number) =>
  Effect.gen(function* () {
    const key = yield* JwtKey.fromPkcs8Pem(pem, { alg: "RS256" });
    return yield* Jwt.sign({ iat: nowSeconds - 60, exp: nowSeconds + 540, iss: appId }, key);
  });

对照发行人公布的密钥校验

把发行人交给你 forIssuer,从来没有人从符号读取: 发行者决定哪些密钥是信任的。 总是通过 audience 对于一个共享的发行者,其一键为每个依赖方设置了标志.

import { JwksResolver, Jwt } from "@effected/jwt";
import { Schema } from "effect";

const Claims = Schema.Struct({ sub: Schema.String });

const verify = (token: string) =>
  Jwt.verify(token, {
    key: JwksResolver.forIssuer("https://issuer.example"),
    claims: Claims,
    issuer: "https://issuer.example",
    audience: "my-service",
  });
// Effect<{ readonly sub: string }, JwtError, JwksResolver | Signature>

检查按此顺序进行:签名,然后 exp 现在, iss, (中文(简体) ), aud, (中文(简体) ), exp 未通过, nbf 到达,你的 claims 计划,最后 iat 未来不会. clockTolerance 财务报告和审定财务报表 requireExpiry 调整默认值.

用您持有的密钥校验

key 是一个 VerificationKey,或从符号头到一的函数.

import { Jwk, Jwt, JwtKey } from "@effected/jwt";
import { Effect, Schema } from "effect";

const verifyWith = (jwk: Jwk, token: string) =>
  Effect.gen(function* () {
    const key = yield* JwtKey.fromJwk(jwk);
    return yield* Jwt.verify(token, { key, claims: Schema.Struct({ sub: Schema.String }) });
  });

Jws 在没有索赔规则的情况下是同一签字层(Jws.sign, (中文(简体) ), Jws.verify),以及 Jws.decodeUnverified 读取符号头和有效载荷作为同步 Result,用于路由 kid 或者说 iss 在选择密钥之前。 永远不要相信它回来.

算法

每个不对称算法核心设备: RS256, (中文(简体) ), RS384, (中文(简体) ), RS512, (中文(简体) ), PS256, (中文(简体) ), PS384, (中文(简体) ), PS512, (中文(简体) ), ES256, (中文(简体) ), ES384, (中文(简体) ), ES512 财务报告和审定财务报表 EdDSA (Ed25519) (英语). 该算法出自密钥,从不给符头,2048位以下的RSA密钥被拒绝. HMAC 被拒绝, 因为密钥集中公布的密钥绝不能作为共享密钥; 对于 HMAC 使用 Core 的密钥 Jwk.importSecret 带有核心 Jwt。 。 。 . alg: "none" 永远不会被接受.

错误

每一次失败都是 JwtError路径 reason永远不要 message 或者说 detail当核心产生故障时 JoseError 这是 cause。 。 。 .

reason含义
malformed不是紧凑的JWS:错误的片段计数,非冠基64url,一个不是JOSE头的片头, alg: "none" 或未知算法,a crit 或者说 b64 或不是JSON的有效载荷.
unsupportedAlgorithm符号或JWK命名为HMAC(或其他非不对称)算法. 未解决密钥 .
algorithmMismatch标志 alg 不是钥匙的算法,也不是JWK的算法 alg 与所需的不同.
badSignature签名不验证 .
unknownKid组合中没有匹配符号算法的密钥和 kid,或几个做.
expiredexp 已经过去了,超越了容忍.
notYetValidnbf 未来,或 iat 是,超越宽容.
wrongIssueriss 缺少或没有被接受的发行人.
wrongAudienceaud 缺少或没有被接受的听众.
claims注册债权有错误的类型, exp 缺少,有效载荷 不是JSON物体,你的 claims schema拒绝了,否则钟容无效.
key关键材料没有导入:一个不正确或不支持的PEM,一个2048位以下的RSA密钥,一个JWK,其类型,曲线, use 或者说 key_ops 无法验证 .
jwksFetch无法发现或获取密钥集: 无法获取、 缓慢、 超大小、 不 https:,转出 https:,一个发现文件,指定另一个发行人,或者一个没有支持密钥的集.

一个符号字符串不是身份:ECDSA签名是可商的,所以一个被签名的有效载荷可以有两个有效的符号字符串. 检测在核实的索赔中重放和撤销(jti,或 iss 与 sub 财务报告和审定财务报表 iat),从未在符号文本上.

测试

@effected/jwt/testing 出口 TestIssuer: 生成的密钥对, 用于邮票的签名符 iss, (中文(简体) ), iat 还有十分钟 exp,以及 resolverLayer真实的 JwksResolver 在一个记忆中 HttpClient 为发行人的发现文件和密钥集服务.

import { JwksResolver, Jwt } from "@effected/jwt";
import { TestIssuer } from "@effected/jwt/testing";
import { Effect, Schema } from "effect";

const program = Effect.gen(function* () {
  const issuer = yield* TestIssuer.make({ issuer: "https://issuer.test" });
  const token = yield* issuer.sign({ aud: "my-app", sub: "user-1" });
  return yield* Jwt.verify(token, {
    key: JwksResolver.forIssuer("https://issuer.test"),
    claims: Schema.Struct({ sub: Schema.String }),
    issuer: "https://issuer.test",
    audience: "my-app",
  }).pipe(Effect.provide(issuer.resolverLayer));
});
// provide CryptoLive: TestIssuer and Jwt.verify both need Signature

提供 resolverLayer 当它依赖于缓存或旋转时 整个测试一次. TestIssuer.rotate(issuer, kid) 在新键下添加密钥 kid- 解析器最多每30秒调试一次 TestClock 在用新密钥验证前。 与 @effect/vitest,提供 Signature 每个测试(layer(CryptoLive, { buildPerTest: true }):为整个区块建造的一层 TestClock 整个测试.

许可证

麻省理工学院

版本与发布记录

@effected/jwt 共发布 13 个版本,首次发布于 2026/10/10;过去 12 个月发布了 13 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.10.0latest2026/11/102 天前
0.9.12026/11/094 天前
0.9.02026/11/0310 天前
0.8.02026/11/0112 天前
0.7.02026/10/2915 天前
0.6.02026/10/2420 天前

关于 @effected/jwt 的常见问题

@effected/jwt 是什么?

JWS,JWT,JWK和JWKS在WebCrypto上签名并验证Effect v4,工人安全.

如何安装 @effected/jwt?

在项目目录运行 npm install @effected/jwt,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:effect(~4.1.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@effected/jwt 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@effected/jwt 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@effected/jwt 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24.11.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@effected/jwt 可以商用吗?

@effected/jwt 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@effected/jwt 的下载量有多少?

根据 npm 官方下载统计,@effected/jwt 在 2026/10/13 – 2026/11/11 这 30 天内被下载 10,200 次,日均约 340 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@effected/jwt 还在维护吗?

最新版本 0.10.0 发布于 2026/11/10(2 天前);至今共发布 13 个版本,其中过去 12 个月发布了 13 个;首次发布于 2026/10/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。