news 2026/9/12 10:59:58

Activepieces Managed Auth 深度解析:基于 JWT 的嵌入式认证与外部 Token 交换机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Activepieces Managed Auth 深度解析:基于 JWT 的嵌入式认证与外部 Token 交换机制

Activepieces Managed Auth 深度解析:基于 JWT 的嵌入式认证与外部 Token 交换机制

【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces

Managed Auth(托管认证)是 Activepieces 面向 SaaS 厂商提供的嵌入式认证能力:厂商在自己的产品中嵌入 Activepieces 流程构建器,由厂商后端用 RSA 私钥签发短期 JWT,换取 Activepieces 侧完整的AuthenticationResponse(含访问令牌),实现"用户、项目、权限与并发限制全部由外部 Token 的 claims 自动供给"。本文以仓库中 managed-auth.md 为骨架,结合服务端、前端与共享包的源码实现,完整讲解其架构、Token 协议、交换流程与安全边界,读完即可在自己的 SaaS 产品中接入这一认证链路。

一、什么是 Managed Auth:把构建器嵌进你的产品

在 Activepieces 中,"Embedding" 指 SaaS 厂商(下称"厂商")将 Activepieces 的流程构建器嵌入自有产品页面,让终端用户无需注册 Activepieces 账号即可直接编排流程。难点在于:Activepieces 需要为每一位终端用户自动创建账号与项目,并严格控制其可见的 Pieces 范围与并发能力——这不能靠用户手动注册完成,必须由厂商后端在每次会话启动时"代为认证"。

Managed Auth 正是为此设计的服务端到服务端认证协议:

  1. 厂商后端持有一把 RSA私钥,用它签发一个短时 JWT(External Access Token);
  2. JWT 通过 Activepieces 的 Embed SDK 传递给服务端端点POST /v1/managed-authn/external-token;
  3. 服务端用存储在 Activepieces 侧的公钥验签,再从 claims 中提取externalUserIdexternalProjectId、角色、Piece 范围、并发池等信息;
  4. 服务端自动完成"用户/项目/权限"的按需创建或复用,最终返回一个完整AuthenticationResponse(含 Activepieces 访问令牌),前端 SDK 据此以该用户身份进入构建器。

值得注意的是,该功能受平台套餐platform.plan.embeddingEnabled门控,但门控位于 Signing Key 模块,而非 external-token 端点本身。从源码看,signing-key-module.ts 在注册/v1/signing-keys路由前挂载了platformMustHaveFeatureEnabled((platform) => platform.plan.embeddingEnabled)钩子;而 managed-authn-controller.ts 中的端点配置为securityAccess.public()——其安全性完全由 JWT 签名本身保证(详见"安全边界"一节)。

二、整体架构与一次完整交换的时序

从 app.ts 可见,managedAuthnModulesigningKeyModuleApEdition.CLOUDApEdition.ENTERPRISE两个版本中均被注册(分别为 app.ts 与 app.ts),服务端模块注册路径为:

  • /v1/managed-authn— managed-authn-module.ts 注册控制器前缀;
  • /v1/signing-keys— signing-key-module.ts 注册签名密钥 CRUD。

一次完整交换的时序如下:

厂商后端 Activepieces Server | | | 1. 用 RSA 私钥签发 JWT (short-lived) | |------------------------------------->| (不经过 AP,由厂商自行签发) | | | 2. Embed SDK 调用 POST /v1/managed-authn/external-token |------------------------------------->| externalTokenExtractor: | | - 按 header kid 找到 Signing Key | | - 用公钥 RS256 验签、解析 payload | | getOrCreateProject (按 externalProjectId) | | 可选:更新 displayName / upsert 并发池 | | applyProjectPieceAccess (无条件执行) | | getOrCreateUser (按 externalUserId + 哈希邮箱) | | upsert 项目成员 (默认 EDITOR) | | 签发 7 天 AP 访问令牌 |<-------------------------------------| 返回 AuthenticationResponse

其中服务端的编排逻辑全部位于 managed-authn-service.ts 的externalToken方法,而 JWT 校验与 payload 解析位于 external-token-extractor.ts。

三、三个关键领域概念

3.1 Signing Key:RSA 密钥对

  • 公钥存储在 Activepieces 平台侧(仅保存公钥,服务端无法伪造外部 Token);
  • 私钥由厂商自己保管,用于签发 JWT;
  • JWT 的 header 中kid字段 = Signing Key ID,服务端据此从数据库解析对应的公钥。

从 signing-key-generator.ts 可以看到服务端生成密钥对的方式:使用 Node.jscrypto.generateKeyPair,算法rsa模长 4096 位,公钥与私钥均使用pkcs1编码的 PEM 格式。而 signing-key-service.ts 的add方法在保存时只入库公钥,privateKey仅在创建响应中一次性返回给厂商——这意味着私钥一旦丢失无法从 Activepieces 侧找回,只能删除重建。

3.2 externalUserId:厂商用户 ID

厂商自己的用户标识,用于在 Activepieces 中确定性映射用户。它不会以原始形式入库,而是与platformId一起哈希为确定性的身份邮箱:

sha256("managed_<platformId>_<externalUserId>")

对应源码为 managed-authn-service.ts 的generateEmailHash,哈希结果还会经过trim().toLowerCase()清洗以保证比较一致性。因此 Managed Auth 用户永远没有真实邮箱,其身份标识完全由externalId维系。

3.3 externalProjectId:厂商项目 ID

厂商的项目标识,通过项目的externalId字段映射到 Activepieces 项目。服务端按(platformId, externalProjectId)查找,不存在则创建一个TEAM 类型项目(owned by 平台 owner),见 managed-authn-service.ts。

四、前置准备:创建 Signing Key

在调用 external-token 端点之前,厂商必须先通过平台 API 创建一把签名密钥:

# 创建签名密钥(需要平台级管理员权限,受 embeddingEnabled 套餐门控) POST /v1/signing-keys Content-Type: application/json { "displayName": "my-saas-production" }

响应中会包含privateKey(仅此一次):

{ "id": "sk_xxxx", "platformId": "platform_xxxx", "publicKey": "-----BEGIN RSA PUBLIC KEY-----...", "privateKey": "-----BEGIN RSA PRIVATE KEY-----...", "algorithm": "RSA", "displayName": "my-saas-production" }

Signing Key 的完整 CRUD(增、查列表、按 id 查、删)由 signing-key-service.ts 提供,删除时按(platformId, id)双重限定,防止跨平台误删。

五、服务端签发 JWT:Token Payload 的四个版本

外部 Token 的 payload 采用 Zod schema 解析,由 external-token-extractor.ts 的externalTokenPayload()定义。z.union的排列顺序是v4 → v3 → v2(最具体优先),因为 v2 的 schema 会剥离未知键,若放在前面会"吞掉" v3/v4 的版本特定字段。

v1/v2(无version字段,legacy)

v2 在 v1 基础上扩展了role、嵌套pieces对象、并发池字段:

{ "externalUserId": "user_123", "externalProjectId": "project_456", "firstName": "Jane", "lastName": "Doe", "role": "EDITOR", "pieces": { "filterType": "ALLOWED", "tags": ["tag-a"] }, "concurrencyPoolKey": "pool-1", "concurrencyPoolLimit": 10 }
  • role:可选的平台自定义项目角色名,缺省回退到DefaultProjectRole.EDITOR(见 external-token-extractor.ts 的getProjectRole);
  • pieces.filterTypepieces.tags:legacy 的 Piece 范围表达;
  • concurrencyPoolKey/concurrencyPoolLimit:可选并发池配置,二者必须同时出现才会生效(见服务端判空逻辑 managed-authn-service.ts)。

v3(version: "v3")

嵌套的pieces被拍平为顶层字段:

{ "version": "v3", "externalUserId": "user_123", "externalProjectId": "project_456", "firstName": "Jane", "lastName": "Doe", "piecesFilterType": "ALLOWED", "piecesTags": ["tag-a"] }

v4(version: "v4")

pieceSet为必填,其值是 Piece Set 的key(即命名 Piece Set 的标识,不再是 tag 列表):

{ "version": "v4", "externalUserId": "user_123", "externalProjectId": "project_456", "firstName": "Jane", "lastName": "Doe", "pieceSet": "my-named-piece-set-key" }

三个版本的解析分支见 external-token-extractor.ts 的extractPieces:v4 提取pieceSetKey;v3 提取piecesFilterType+piecesTags;v1/v2 从嵌套pieces提取;均无则回退到PiecesFilterType.NONE

六、externalToken 交换流程:逐步骤源码解读

POST /v1/managed-authn/external-token的请求体仅含一个字段externalAccessToken,由共享包中的 managed-authn-requests.ts 定义(注释还提醒:改动该结构需同步更新 embed-sdk,因其不能有依赖)。服务端 managed-authn-service.ts 的externalToken方法按以下步骤执行:

步骤 1:校验外部 Token

externalTokenExtractor.extract()(见 external-token-extractor.ts):

  1. jwtUtils.decode取出 header,若缺少kid直接抛出INVALID_BEARER_TOKEN(signing key id not found in the header);
  2. kid查库获取 Signing Key(含平台公钥);
  3. RS256(常量JwtSignAlgorithm.RS256,见 external-token-extractor.ts)验签并解析 payload,不校验 issuer(传入issuer: null);
  4. 解析出ExternalPrincipal,其中platformId取自Signing Key 所属平台,而不是 payload——这是防止跨平台冒用的关键设计。

验签失败的错误消息会原样透传回调用方,便于厂商排查。

步骤 2:Get or Create Project

(platformId, externalProjectId)查找项目(managed-authn-service.ts):

  • 命中则直接复用;
  • 未命中则读取平台,创建一个displayName = externalProjectId、owner 为平台 owner、type = ProjectType.TEAM且带externalId的项目。

步骤 3:可选地更新显示名与并发池

  • 若 payload 含projectDisplayName,则更新项目显示名(managed-authn-service.ts);
  • concurrencyPoolKeyconcurrencyPoolLimit同时非空,则 upsert 并发池并绑定到项目(managed-authn-service.ts)——这使厂商可以在外部 Token 中按项目指定并发上限。

步骤 4:应用 Piece 访问范围(无条件执行)

applyProjectPieceAccess在每次交换时都会无条件运行,此处没有managePiecesEnabled门控(managed-authn-service.ts)。其回退顺序为:

  1. 显式pieceSetkey(v4)→ 按(platformId, key)查找命名 Piece Set,命中即assignProject;
  2. 未命中 → 取legacypiecesTags的第一个 tag(仅当filterType === ALLOWED,多 tag 场景未启用,每个 tag 对应一个 key = tagName 的命名 Set);
  3. 仍无匹配(或 targetKey 为 undefined)→ 回退到平台的Default 默认 Piece Set,且当指定了 key 却查不到时会输出 warn 日志:pieceSet key "<key>" not found — falling back to default

值得注意的是,项目套餐(project plan)不会被写入——外部 Token 只影响 Piece 集合与并发池,不改变项目的计费套餐。

步骤 5:Get or Create User

getOrCreateUser(managed-authn-service.ts)按(platformId, externalId)查找用户:

  • 存在则直接返回;
  • 不存在则先getOrCreateUserIdentity创建身份(邮箱 =sha256("managed_<platformId>_<externalUserId>")哈希值,密码为随机生成、provider: JWTverified: true,见 managed-authn-service.ts),再创建platformRole: MEMBER的用户。

步骤 6:Upsert 成员关系并签发访问令牌

  • (projectId, userId, projectRoleName)upsert 项目成员,角色默认来自第 5 节解析的projectRole(缺省EDITOR);
  • 读取身份后调用accessTokenManager.generateToken,签发7 天(7 * 24 * 60 * 60秒)的 Activepieces 访问令牌(managed-authn-service.ts);
  • 返回完整AuthenticationResponse:包含idplatformRolestatusexternalIdplatformId、姓名、email(哈希邮箱)、trackEventsnewsLetterverifiedtokenprojectId(managed-authn-service.ts)。

控制器在返回前还会上报USER_SIGNED_UP事件,source: 'managed'(见 managed-authn-controller.ts),方便平台侧追踪嵌入式注册来源。

七、前端与 Embed SDK 侧:拿到 Token 之后

服务端返回的AuthenticationResponse由嵌入方前端接收。仓库中对应的 API 客户端是 managed-auth-api.ts 的managedAuthApi.generateApToken,它封装了对/v1/managed-authn/external-token的 POST 调用,并从@activepieces/shared引入ManagedAuthnRequestBodyAuthenticationResponse类型。

在嵌入路由中,该客户端被实际调用:见 embed/index.tsx(managedAuthApi.generateApToken({ ... }))。典型集成方式为:

  1. 厂商后端签发外部 JWT(见第五节 payload 结构);
  2. 厂商前端将 JWT 交给 Activepieces Embed SDK;
  3. SDK 调用POST /v1/managed-authn/external-token换取 AP 访问令牌;
  4. 携带该令牌以对应projectId进入构建器,即完成了"免注册嵌入式登录"。

八、安全边界与已知注意事项(Gotchas)

  1. 端点是公开的:POST /v1/managed-authn/external-token配置为securityAccess.public(),没有附加 API Key 或会话校验——JWT 签名本身就是全部安全。因此厂商必须确保私钥安全保管,并签发短时Token。
  2. 平台归属取自 Signing Key 而非 payload:platformIdkid解析出的签名密钥决定,外部用户无法通过篡改 claims 进入其他平台。
  3. 外部用户没有真实邮箱:身份邮箱是sha256("managed_<platformId>_<externalUserId>")的确定性哈希,不具备密码找回等邮件能力;UserIdentityProvider.JWT也表明其身份来源。
  4. 项目套餐不被写入:外部 Token 只控制 Piece Set 与并发池绑定,不修改项目 plan。
  5. v2 schema 会剥离未知键:z.union必须保持 v4 → v3 → v2 的从前往后顺序,否则 v3/v4 的version特定字段会被静默丢弃,导致解析错误。
  6. 私钥只在创建时返回一次:signingKeyService.add只持久化公钥,privateKey 一旦丢失需删除重建。

九、关键文件索引

层次路径职责
文档managed-auth.md本主题的核心知识笔记(路径已核实)
服务端模块managed-authn-module.ts注册/v1/managed-authn前缀
服务端控制器managed-authn-controller.ts唯一的POST /external-token路由
服务端编排managed-authn-service.ts项目/用户/成员/Piece 范围/令牌签发
JWT 校验external-token-extractor.tsRS256 验签、v1/v2/v3/v4 payload 解析
签名密钥signing-key-module.tsembeddingEnabled套餐门控
密钥生成signing-key-generator.ts4096 位 RSA、pkcs1 PEM
共享契约managed-authn-requests.ts请求体结构(externalAccessToken)
前端客户端managed-auth-api.tsgenerateApTokenAPI 封装
注册入口app.tsCLOUD / ENTERPRISE 版本挂载模块

十、总结

Managed Auth 是 Activepieces 嵌入式能力的认证基石:以 RSA 签名 JWT 作为信任根,通过kid解析平台归属,用externalUserId/externalProjectId实现用户与项目的确定性幂等映射,再以 v1–v4 多版本 payload 逐步演进 Piece 范围控制(从嵌套pieces到命名 Piece Set 的pieceSetkey),最后签发 7 天访问令牌供 Embed SDK 使用。理解其 Token 版本、回退语义与"端点公开、签名即安全"的边界,是正确、安全地将其接入自有 SaaS 产品的关键。

【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 10:58:59

AI技术如何突破跨境电商语言壁垒

1. 义乌防雾面罩的16秒神话背后&#xff1a;AI如何击穿跨境语言壁垒去年冬天&#xff0c;一款来自义乌的防雾面罩在TikTok上突然爆火。从第一个测评视频发布到登上亚马逊美区运动防护类目榜首&#xff0c;只用了16秒。这个看似偶然的案例背后&#xff0c;隐藏着跨境商家用AI技术…

作者头像 李华
网站建设 2026/9/12 10:58:48

线上接单5-8元/单的高效运营指南

1. 项目概述"在线接单 5-8/一单"这个标题描述的是一个典型的线上服务交易场景。作为从业多年的自由职业者&#xff0c;我理解这指的是通过互联网平台接收任务订单&#xff0c;每单报酬在5-8元之间的服务模式。这种模式常见于文案写作、数据标注、简单设计等标准化程度…

作者头像 李华
网站建设 2026/9/12 10:57:20

AI邮件助手误删事故:权限控制与数据恢复的教训

1. 事件背景&#xff1a;AI失控引发的数据灾难那天早上&#xff0c;我像往常一样测试新开发的AI邮件助手。这个基于大语言模型的智能系统被设计用来帮助用户自动分类、归档和回复邮件。在测试环境中运行两周后表现良好&#xff0c;于是我决定用个人邮箱账号做真实场景测试——这…

作者头像 李华
网站建设 2026/9/12 10:56:42

服务器打包发布时jar包加载配置文件的顺序

一、在idea中使用mvn clean package将springCloud项目进行打包。 二、遇见的问题 发现远程windows服务器上文件夹也有一个bootstrap.yml。那本地也有一个bootstrap.yml&#xff0c;而且本地还配置了nacos&#xff0c;那这三个配置文件的加载顺序是什么呢&#xff1f; 三、经…

作者头像 李华
网站建设 2026/9/12 10:56:34

这次终于选对了!盘点2026年实力封神的的AI论文平台

一天写完毕业论文在2026年已不再是天方夜谭。以下是2026年最炸裂、实测能大幅提速的AI论文平台&#xff0c;覆盖选题构思、文献综述、数据整理、降重润色等核心场景&#xff0c;帮你高效搞定论文写作。 一、全流程王者&#xff1a;一站式搞定论文全链路&#xff08;一天定稿首选…

作者头像 李华