ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Activepieces Piece 认证模式全解析:SecretText、OAuth2、Basic、CustomAuth 与连接标识符实战指南

Activepieces Piece 认证模式全解析:SecretText、OAuth2、Basic、CustomAuth 与连接标识符实战指南 Activepieces Piece 认证模式全解析SecretText、OAuth2、Basic、CustomAuth 与连接标识符实战指南【免费下载链接】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导读在 Activepieces 中开发一个 Piece集成组件时认证Authentication定义是决定连接体验与安全性的第一道关卡。无论是对接只签发单个 API Key 的简单服务还是需要 OAuth2 授权码流程的 Google、Slack抑或是需要「实例 URL 账号密码」组合登录的企业自托管系统Piece 框架都提供了对应的认证类型。本文基于仓库中的认证模式指南.agents/skills/piece-builder/auth-patterns.md逐一讲解PieceAuth的六种认证形态——SecretText、OAuth2、BasicAuth、CustomAuth含 Token 刷新、连接标识符getConnectionIdentifier与None并结合仓库内真实 Piece 源码与框架底层实现说明每种模式在validate校验、action/trigger 运行时读取凭据的具体写法帮助你在构建 Piece 时选出正确模式并写出可上线的认证代码。一、认证体系概览PieceAuth提供的六种形态从框架源码 packages/pieces/framework/src/lib/property/authentication/index.ts 可以看到PieceAuth暴露了五个构造器SecretText、OAuth2、BasicAuth、CustomAuth、OIDC以及返回undefined的None()它们分别对应PropertyType中的不同枚举值最终在连接App Connection层映射为AppConnectionType中的SECRET_TEXT、OAUTH2、BASIC_AUTH、CUSTOM_AUTH、OIDC、NO_AUTH。本指南覆盖其中六种最常用的模式核心差异在于用户需要输入什么、凭据以什么形态出现在validate与 action/trigger 上下文中认证模式适用场景validate回调中的auth形态action/trigger 中的读取方式SecretText单一 API Key / Token普通字符串context.auth.secret_textOAuth2授权码流程Google、Slack、GitHub 等完整连接对象context.auth.access_token、context.auth.props、context.auth.dataBasicAuth用户名 密码扁平对象context.auth.username、context.auth.passwordCustomAuth多字段组合URL Key、区域 凭据等扁平 props 对象context.auth.props.fieldCustomAuth refresh短时 Token登录换 JWT扁平 props 对象context.auth.access_token服务端缓存None公共 API / 工具类 Piece无context.auth不可用说明OIDC也是框架内置的认证类型见 oidc-prop.ts本指南聚焦认证模式文档主讲的六种常用形态。二、SecretText最常见的单 Key 认证2.1 定义与校验SecretText是最常用的认证类型适用于签发单个 API Key 或 Token 的简单 API。在validate回调中auth就是一个普通字符串而在 action/trigger 中它是完整的连接对象需要通过context.auth.secret_text读取密钥。import { PieceAuth } from activepieces/pieces-framework; import { httpClient, HttpMethod } from activepieces/pieces-common; export const myAppAuth PieceAuth.SecretText({ displayName: API Key, description: Get your API key from https://app.example.com/settings/api, required: true, validate: async ({ auth }) { try { await httpClient.sendRequest({ method: HttpMethod.GET, url: https://api.example.com/v1/me, headers: { Authorization: Bearer ${auth} }, }); return { valid: true }; } catch (e) { return { valid: false, error: Invalid API Key }; } }, });action/trigger 中读取密钥async run(context) { const apiKey context.auth.secret_text; // ... }2.2 底层类型与框架行为从框架源码 secret-text-property.ts 看SecretTextProperty的值结构被定义为{ auth: z.string() }PieceAuth.SecretText仅补充type: PropertyType.SECRET_TEXT后返回。required泛型参数会直接决定SecretTextPropertytrue/SecretTextPropertyfalse的类型从而影响context.auth.secret_text是否可能为undefined。2.3 真实案例Stripe仓库内 Stripe Piece 的认证正是这一模式的代表packages/pieces/community/stripe/src/index.ts用户在 Stripe 控制台获取Secret API Key后填入连接validate通过请求https://api.stripe.com/v1/customers验证密钥有效性失败时返回Invalid API Key. Please check the key and try again.。而其自定义 API 调用动作createCustomApiCallAction的authMapping中读取的正是auth.secret_textcreateCustomApiCallAction({ baseUrl: () https://api.stripe.com/v1, auth: stripeAuth, authMapping: async (auth) ({ Authorization: Bearer ${auth.secret_text}, }), })这条真实代码同时印证了本指南的核心规则validate里是裸字符串action 里是完整连接对象。三、OAuth2标准授权码流程3.1 基础配置对于 Google、Slack、GitHub 这类走 OAuth2 授权流程的服务使用PieceAuth.OAuth2import { PieceAuth } from activepieces/pieces-framework; export const myAppAuth PieceAuth.OAuth2({ required: true, authUrl: https://app.example.com/oauth/authorize, tokenUrl: https://app.example.com/oauth/token, scope: [read, write], // 可选配置 // pkce: true, // pkceMethod: S256, // prompt: consent, // grantType: OAuth2GrantType.AUTHORIZATION_CODE, // authorizationMethod: OAuth2AuthorizationMethod.HEADER, // extra: { audience: https://api.example.com }, });3.2 可选参数详解对照框架源码 oauth2-prop.tsOAuth2支持以下可选参数pkce/pkceMethod是否启用 PKCEProof Key for Code ExchangepkceMethod取值为plain或S256S256 是更安全的推荐值prompt授权页提示行为取值none、consent、login、omitomit表示不发送 prompt 参数grantType授权类型来自activepieces/core-piece-types的OAuth2GrantType枚举如AUTHORIZATION_CODE、CLIENT_CREDENTIALS还支持BOTH_CLIENT_CREDENTIALS_AND_AUTHORIZATION_CODE这种「两种都允许」的组合值authorizationMethodclient_id/client_secret 的传递方式OAuth2AuthorizationMethod.HEADER放进请求头或BODY放进请求体枚举定义见同一文件的第 11-14 行extra需要额外传给 token 端点的键值对如某些服务要求的audience。3.3 在 action/trigger 中读取OAuth2 连接对象包含三部分context.auth.access_token—— OAuth2 access tokencontext.auth.props?.[key]—— 当认证定义了额外props如数据中心、区域、子域时的取值context.auth.data—— 提供商返回的原始 token 响应含 refresh token、scope 等。async run(context) { const token context.auth.access_token; const region context.auth.props?.[region] as string; // ... }这三部分的类型定义见 oauth2-prop.ts 中的OAuth2PropertyValue{ access_token: string; props?: ...; data: Recordstring, any }。注意data是「原始响应」——例如 Slack 的data.team、data.authed_user都来自这里。3.4 自定义 API 调用动作中的类型推断在createCustomApiCallAction中只要把auth声明为myAppAuthauthMapping回调的auth参数就已经具备正确类型无需任何类型断言直接读取auth.access_token即可createCustomApiCallAction({ baseUrl: () https://api.example.com, auth: myAppAuth, authMapping: async (auth) ({ Authorization: Bearer ${auth.access_token}, }), })3.5 真实案例GitHub 与 Zoho CampaignsGitHubpackages/pieces/community/github/src/index.ts标准 OAuth2 授权码流程的典型实现Zoho Campaignspackages/pieces/community/zoho-campaigns/OAuth2配合额外props的案例——用户需要选择数据中心/区域代码通过context.auth.props读取。四、BasicAuth用户名 密码适用于使用 username/password 认证的 APIimport { PieceAuth } from activepieces/pieces-framework; import { httpClient, HttpMethod, AuthenticationType } from activepieces/pieces-common; export const myAppAuth PieceAuth.BasicAuth({ displayName: Connection, required: true, username: { displayName: Username, description: Your account username, }, password: { displayName: Password, description: Your account password, }, validate: async ({ auth }) { try { await httpClient.sendRequest({ method: HttpMethod.GET, url: https://api.example.com/v1/me, authentication: { type: AuthenticationType.BASIC, username: auth.username, password: auth.password, }, }); return { valid: true }; } catch (e) { return { valid: false, error: Invalid credentials }; } }, });action/trigger 中读取const username context.auth.username; const password context.auth.password;框架源码 basic-auth-prop.ts 中BasicAuthProperty的值结构为{ username: string; password: string }。注意PieceAuth.BasicAuth在 index.ts 中强制required: true——BasicAuth 不允许可选连接必须同时提供用户名和密码。在validate中做真实校验时推荐使用httpClient的authentication字段并指定AuthenticationType.BASIC由 HTTP 客户端负责生成Authorization: Basic base64头避免手写编码出错。五、CustomAuth多字段组合认证5.1 基本形态当 API 需要多个字段才能完成认证——例如「实例 URL API Key」或「区域 凭据」——使用PieceAuth.CustomAuthimport { PieceAuth, Property } from activepieces/pieces-framework; export const myAppAuth PieceAuth.CustomAuth({ displayName: Connection, required: true, props: { base_url: Property.ShortText({ displayName: Instance URL, description: e.g. https://mycompany.example.com, required: true, }), api_key: PieceAuth.SecretText({ displayName: API Key, required: true, }), }, validate: async ({ auth }) { try { await httpClient.sendRequest({ method: HttpMethod.GET, url: ${auth.base_url}/api/v1/me, headers: { Authorization: Bearer ${auth.api_key} }, }); return { valid: true }; } catch (e) { return { valid: false, error: Invalid connection details }; } }, });5.2 关键差异validate扁平、action 嵌套CustomAuth 最容易踩坑的点是两处auth形态不同在validate回调中收到的是扁平形状——直接auth.base_url、auth.api_key在 action/trigger 中字段挂在props下——必须用context.auth.props.base_url、context.auth.props.api_key。async run(context) { const baseUrl context.auth.props.base_url; const apiKey context.auth.props.api_key; // ... }5.3 允许的 props 类型从框架源码 custom-auth-prop.ts 的CustomAuthProps联合类型可见CustomAuth 的 props 支持ShortText、LongText、SecretText、Number、Checkbox、StaticDropdown、StaticMultiSelectDropdown、MarkDown其中SecretText用于密码/密钥类字段输入框会打码StaticDropdown/StaticMultiSelectDropdown用于固定选项MarkDown可用于在连接表单里插入说明文案。5.4 真实案例WordPress 与 MattermostWordPresspackages/pieces/community/wordpress/src/index.ts实例 URL 用户名 应用密码Application Password组合的典型 CustomAuthMattermostpackages/pieces/community/mattermost/src/index.ts服务器 URL 个人访问令牌PAT的组合。这两个例子都体现了 CustomAuth 的价值把「连接哪个实例」和「用谁的凭据」两个信息封装在同一个连接对象里。六、CustomAuth Token 刷新避免 429 的关键6.1 为什么需要 refresh当 API 要求先用「用户名/密码」调用登录接口换取**短时 Token如 JWT**时如果不做缓存每个 action 执行都会触发一次登录请求——高频率工作流会迅速打爆限流产生429 Rate Limit 错误。解决方案是在 CustomAuth 上增加refresh字段让Activepieces 在服务端缓存 Token 并自动续期Token 会在过期前 15 分钟自动刷新对短时 Token刷新时机被钳制clamped在其生命周期的一半以内避免每次调用都刷新。export const myAppAuth PieceAuth.CustomAuth({ displayName: Connection, required: true, props: { baseUrl: Property.ShortText({ displayName: Instance URL, required: true }), username: Property.ShortText({ displayName: Username, required: true }), password: PieceAuth.SecretText({ displayName: Password, required: true }), }, validate: async ({ auth }) { // validate as usual }, refresh: { generate: async ({ auth }) { // auth 是扁平 props 形状auth.baseUrl、auth.username 等 const res await httpClient.sendRequest{ token: string }({ method: HttpMethod.POST, url: ${auth.baseUrl}/api/auth/login, body: { username: auth.username, password: auth.password }, }); return { access_token: res.body.token, // expires_in: 3600, // 可选单位秒——API 不返回过期时间时可省略 }; }, defaultExpiresIn: 3300, // 兜底 TTL秒默认 3300 55 分钟 }, });6.2 运行时读取在 action/trigger 中context.auth.access_token保存的是服务端缓存的 Token此处不会触发登录请求原始凭据字段仍通过context.auth.props.field读取async run(context) { const token context.auth.access_token; // 服务端缓存不会在这里调用登录接口 const baseUrl context.auth.props.baseUrl; await httpClient.sendRequest({ method: HttpMethod.GET, url: ${baseUrl}/api/resource, headers: { Authorization: Bearer ${token} }, }); }6.3 refresh 的底层语义框架类型定义 custom-auth-prop.ts 对CustomAuthRefresh给出了精确语义generate接收{ auth: StaticPropsValueT; server }auth是扁平的 props 值返回{ access_token: string; expires_in?: number }expires_inToken 生命周期秒。省略时使用defaultExpiresIn或框架默认值设为0表示永不过期Token 会被无限期缓存、不再刷新defaultExpiresIn当generate未返回expires_in时的兜底 TTL秒0同样表示永不过期服务端在过期前 15 分钟刷新且钳制在生命周期一半以内确保短时 Token 不会被频繁刷新。6.4 真实案例UmamiUmami Piece 的自托管认证packages/pieces/community/umami/src/lib/auth.ts是这一模式的生产级实现const selfHostedAuth PieceAuth.CustomAuth({ displayName: Self-hosted (Username Password), props: { baseUrl: Property.ShortText({ displayName: Instance URL, ... }), username: Property.ShortText({ displayName: Username, ... }), password: PieceAuth.SecretText({ displayName: Password, ... }), }, validate: async ({ auth }) { // POST {baseUrl}/api/auth/login 验证用户名密码 }, refresh: { generate: async ({ auth }) { const baseUrl auth.baseUrl.replace(/\/$/, ); const response await httpClient.sendRequest{ token: string }({ method: HttpMethod.POST, url: ${baseUrl}/api/auth/login, body: { username: auth.username, password: auth.password }, }); return { access_token: response.body.token }; }, // Umami 不返回 expires_in默认 55 分钟保证在典型的 1 小时 JWT 过期前完成刷新 defaultExpiresIn: 3300, }, });该文件还展示了一个进阶技巧Umami 同时导出了selfHostedAuth和cloudAuthSecretText并以数组形式[selfHostedAuth, cloudAuth]传给createPiece——这样同一个 Piece 可以让用户二选一自托管账号密码 或 云端 API Key配合AppConnectionType判别见同文件getBaseUrl/getAuthHeaders实现按连接类型分流。这也解释了框架中PieceAuthProperty[]数组形态的存在意义。七、连接标识符 getConnectionIdentifier让连接列表一目了然7.1 作用与语法getConnectionIdentifier是每种认证类型SecretText、BasicAuth、OAuth2、CustomAuth都可选的回调用于为一条连接解析出人类可读的标签例如账号邮箱或 Slack 的「display-name (workspace)」展示在连接管理 UI 中帮助用户区分多个账号。export const myAppAuth PieceAuth.OAuth2({ required: true, authUrl: https://app.example.com/oauth/authorize, tokenUrl: https://app.example.com/oauth/token, scope: [read, write], getConnectionIdentifier: async ({ auth }) { const response await httpClient.sendRequest{ email: string }({ method: HttpMethod.GET, url: https://api.example.com/v1/me, headers: { Authorization: Bearer ${auth.access_token} }, }); return response.body.email; }, });7.2 使用规则必须是 best-effort把有风险的调用包在try/catch中无法确定时解析为undefined。回调抛出错误会阻塞连接保存OAuth2 优先用通用路径Activepieces 已能从 token 响应的 OIDC claims 中自动推导标识符。只有通用路径覆盖不了时才需要这个钩子——例如Slack 没有按用户维度的 OIDC claim所以需要「工作区名 追加一次users.info调用」来拼出标签只在该提供商确实暴露账号/工作区标签时才加一个没有「who am I」端点的裸 API Key没有任何可解析的内容就不需要实现。7.3 回调形态与框架机制与validate一致回调里的auth是扁平形态SecretText 是字符串、CustomAuth 是扁平 props 对象不是完整连接对象。框架层面common.ts 的注释揭示了一个内部机制由于函数无法通过元数据序列化框架在Piece.metadata()阶段派生出hasConnectionIdentifier布尔标记服务端无需支付一次 engine 往返就能判断该认证是否定义了此钩子。7.4 真实案例SlackSlack 的 OAuth2 认证packages/pieces/community/slack/src/lib/auth.ts是完整实现先尝试从 token 响应的data.team/data.enterprise中取工作区名取不到就返回undefined再通过users.info拿授权用户的 display name / real name / username拼成user (workspace)users.info调用失败时降级为只返回工作区名。全程 best-effort绝不抛错。八、None无认证的公共 API 与工具 Piece对于公开 API 或不需要凭据的工具类 Piece直接使用PieceAuth.None()// 在 createPiece() 中 auth: PieceAuth.None(),从框架源码 index.ts 可以看到None()的实现就是返回undefined。使用None时需注意三点行为差异在createAction()/createTrigger()中省略auth:字段run中context.auth不可用Dropdown 等动态属性收不到auth参数因为根本没有连接对象可传。真实案例packages/pieces/core/qrcode/src/index.tsQR 码生成工具 Piece——纯工具属性无任何网络凭据需求。九、模式选择决策速查综合全文为你的 Piece 选择认证模式时可遵循以下决策链完全不需要凭据公共 API、纯工具→PieceAuth.None()单一 Key/Token 即可→PieceAuth.SecretText()配合validate调一次轻量接口验证标准 OAuth2 授权码流程Google、Slack、GitHub 类→PieceAuth.OAuth2()按需配置pkce、grantType、authorizationMethod、额外props与extra用户名 密码→PieceAuth.BasicAuth()多字段组合URL Key、区域 凭据、账号 Token→PieceAuth.CustomAuth()牢记「validate 扁平、action 走props」多字段 短时 Token→ 在 CustomAuth 上追加refresh用defaultExpiresIn兜底避免每个 action 触发登录造成 429连接列表需要区分账号→ 为上述任意认证类型追加getConnectionIdentifier遵守 best-effort 规则一个 Piece 支持多种认证方式→ 用数组[authA, authB]传给createPiece运行期以AppConnectionType判别参考 Umami 案例。十、总结认证是 Piece 与外部服务之间的信任边界Activepieces 的PieceAuth通过六种模式覆盖了从单 Key 到 OAuth2、从扁平账号到多字段组合的绝大多数场景。本文梳理的要点包括validate回调与 action/trigger 中auth形态的差异、OAuth2 连接对象的三段式结构access_token/props/data、CustomAuth 的「validate 扁平 / props 嵌套」规则、refresh机制的 15 分钟提前刷新与生命周期钳制、getConnectionIdentifier的 best-effort 约束以及无认证 Piece 的None约定。结合 Stripe、Umami、Slack、GitHub、Zoho Campaigns、WordPress、Mattermost 等仓库内真实实现你可以对照.agents/skills/piece-builder/auth-patterns.md快速为自己的 Piece 选定认证方案并直接复用上述代码骨架完成可校验、可读、可长期维护的连接定义。【免费下载链接】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),仅供参考
返回列表