n8n-credentials-and-security-official
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesen8n Credentials and Security
n8n 凭证与安全
Non-negotiables
不可妥协的原则
- Secrets via the credential system, never in text fields or SDK code. API keys, bearer tokens, OAuth secrets, passwords: all go through or the node's
newCredential()parameter. A Set node hardcoding a token and read viacredentialsis a text field with extra steps.{{$json.token}} - List credentials, then bind by ID. Call before configuring an auth-needing node. One match: bind via 2-arg
list_credentials({type})at create time, ornewCredential('Label', 'credId')op onsetNodeCredential. Multiple matches: ask the user which. The one-argupdate_workflowis a placeholder; n8n auto-assigns the most recently edited credential of that type and silently picks wrong when the user has multiples.newCredential('Label') - Credential creation is the user's job, not yours. The n8n MCP doesn't expose credential creation. Tell the user the exact credential type to create in the UI, then reference it by label in your node config. Don't attempt to create credentials programmatically and don't accept secrets in chat to "set up later".
- 机密信息必须通过凭证系统管理,绝不能存入文本字段或SDK代码中。 API密钥、Bearer令牌、OAuth机密、密码:所有这类信息都必须通过 或节点的
newCredential()参数处理。通过Set节点硬编码令牌并以credentials读取的方式,本质上还是把机密放在了文本字段里。{{$json.token}} - 先列出凭证,再通过ID绑定。 在配置需要认证的节点前,调用 。如果找到匹配项:在创建时通过双参数的
list_credentials({type})绑定,或在newCredential('Label', 'credId')中使用update_workflow操作。如果找到多个匹配项:询问用户选择哪一个。单参数的setNodeCredential是占位符;当用户拥有多个同类型凭证时,n8n会自动分配最近编辑的凭证,但可能会静默选错。newCredential('Label') - 凭证创建是用户的工作,而非你的职责。 n8n MCP不提供凭证创建的接口。告知用户在UI中创建指定类型的凭证,然后在节点配置中通过标签引用它。不要尝试以编程方式创建凭证,也不要在对话中接收机密信息以便“稍后设置”。
Strong defaults
强默认规则
- Use native credentials when available. Every native node (Slack, Gmail, Postgres, OpenAI, etc.) has a credential type. Don't reach for generic credential types when a native option exists.
- For multi-header or header-plus-query auth shapes, use the credential type. See
httpCustomAuth.references/CUSTOM_CREDENTIALS.md
- 优先使用原生凭证(如果可用)。 每个原生节点(Slack、Gmail、Postgres、OpenAI等)都有对应的凭证类型。当存在原生选项时,不要使用通用凭证类型。
- 对于多头部或头部+查询参数的认证模式,使用 凭证类型。详见
httpCustomAuth。references/CUSTOM_CREDENTIALS.md
The credential system
凭证系统简介
In n8n, credentials are first-class objects:
- Stored encrypted at rest in the n8n database.
- Referenced by ID from nodes that need them.
- Scoped to projects (Cloud & enterprise) or shared globally (some self-hosted setups).
- Identified by a type slug (googleSheetsOAuth2Api, slackApi, httpHeaderAuth). The slug is what nodes reference and what determines which auth fields the credential collects.
A node that needs auth has a parameter pointing to a credential ID + type. Secret values never appear in workflow JSON. Exporting a workflow leaks the reference, not the secret.
credentialsFor the full model (SDK resolution, rotation, project scoping), see .
references/CREDENTIAL_SYSTEM.md在n8n中,凭证是一等对象:
- 存储时在n8n数据库中加密。
- 需要认证的节点通过ID引用凭证。
- 作用域分为项目级(云版及企业版)或全局共享(部分自托管部署)。
- 由类型标识(googleSheetsOAuth2Api、slackApi、httpHeaderAuth)。该标识是节点引用的依据,同时决定凭证收集的认证字段。
需要认证的节点通过 参数指向凭证ID和类型。机密值永远不会出现在工作流JSON中。导出工作流只会泄露凭证引用,而非机密本身。
credentials如需了解完整模型(SDK解析、轮换、项目作用域),请参阅 。
references/CREDENTIAL_SYSTEM.mdDecision tree: how to authenticate this thing
决策树:如何为服务配置认证
Need to call an external service?
├── Native credential exists (Slack, Gmail, OpenAI, Postgres, ...)?
│ └── Use the native node + its credential type. Done.
│
├── Service is "standard-shaped" (REST + Bearer/Basic/OAuth)?
│ ├── Configure HTTP Request with one of the built-in auth types:
│ │ - Generic OAuth2
│ │ - Header Auth
| | - Bearer Auth (same as header auth but with only field being for actual token)
│ │ - Basic Auth
│ │ - Custom Auth
│ └── See references/HTTP_REQUEST_WITH_AUTH.md
│
└── Service needs multiple static headers, or headers plus query params?
└── Use the httpCustomAuth credential type.
See references/CUSTOM_CREDENTIALS.md需要调用外部服务?
├── 存在原生凭证(Slack、Gmail、OpenAI、Postgres等)?
│ └── 使用原生节点及其对应的凭证类型。操作完成。
│
├── 服务采用“标准格式”(REST + Bearer/基础认证/OAuth)?
│ ├── 配置HTTP Request节点,选择以下内置认证类型之一:
│ │ - 通用OAuth2
│ │ - 头部认证
| | - Bearer认证(与头部认证类似,但仅包含令牌字段)
│ │ - 基础认证
│ │ - 自定义认证
│ └── 参考 `references/HTTP_REQUEST_WITH_AUTH.md`
│
└── 服务需要多个静态头部,或同时需要头部和查询参数?
└── 使用 `httpCustomAuth` 凭证类型。
参考 `references/CUSTOM_CREDENTIALS.md`When the user pastes a secret into a chat
当用户在对话中粘贴机密信息时
This happens. The user types something like:
"Set up a workflow to call Acme API with bearer"sk-abc123def456
What to do:
- Don't put the token in a text field, even temporarily. A Set node that hardcodes the value and is referenced via is a text field with extra steps.
{{$json.token}} - Bind to an existing credential if possible. first; if a match exists, bind via
list_credentials({type})and tell the user which one you used. If none exists, tell them to create one in the UI (Bearer Auth for bearer tokens, Header Auth for custom headers, etc.). Credential creation is still UI-only.setNodeCredential - Treat the pasted secret as compromised, and tell the user to rotate it. Don't soften this. The token has been transmitted to the LLM provider, may persist in chat history, transcripts, and cache layers. Tell them: "Rotate this token as soon as the new credential is set up. Treat it as leaked."
这种情况时有发生。用户可能会输入类似内容:
"设置一个工作流,使用Bearer令牌调用Acme API"sk-abc123def456
处理步骤:
- 不要将令牌放入文本字段,哪怕是临时的。 通过Set节点硬编码值并以表达式引用的方式,本质上还是把机密放在了文本字段里。
- 尽可能绑定到现有凭证。 先调用 ;如果找到匹配项,通过
list_credentials({type})绑定并告知用户使用的是哪一个。如果没有匹配项,告知用户在UI中创建对应类型的凭证(Bearer令牌用Bearer Auth,自定义头部用Header Auth等)。凭证创建仍需通过UI完成。setNodeCredential - 将粘贴的机密视为已泄露,告知用户立即轮换。 不要含糊其辞。该令牌已传输给LLM提供商,可能会保留在对话历史、记录和缓存层中。告知用户:“在新凭证设置完成后,请立即轮换该令牌。将其视为已泄露。”
When no native node exists
当不存在原生节点时
Common case: the user wants a service n8n has no node for. Use HTTP Request with appropriate auth.
- : discovering auth scheme, base URL, common shapes.
references/FINDING_API_DOCS.md - : wiring HTTP Request to a credential.
references/HTTP_REQUEST_WITH_AUTH.md - : when built-in auth types don't fit.
references/CUSTOM_CREDENTIALS.md
常见场景:用户需要使用n8n未提供原生节点的服务。使用HTTP Request节点并配置合适的认证方式。
- :发现认证方案、基础URL、通用格式。
references/FINDING_API_DOCS.md - :将HTTP Request节点与凭证关联。
references/HTTP_REQUEST_WITH_AUTH.md - :当内置认证类型不适用时的处理方法。
references/CUSTOM_CREDENTIALS.md
Reference files
参考文件
| File | Read when |
|---|---|
| You need to understand how credentials are stored, referenced, scoped, or rotated |
| Multi-header / header-plus-query auth in one credential, or per-request signing patterns (HMAC, JWT, webhook validation) |
| Configuring HTTP Request with auth: Bearer, Basic, OAuth, Header Auth |
| The user mentioned a service you don't have node-level knowledge of |
| 文件 | 阅读时机 |
|---|---|
| 你需要了解凭证的存储、引用、作用域或轮换机制时 |
| 需要在单个凭证中配置多头部/头部+查询参数认证,或处理请求签名模式(HMAC、JWT、Webhook验证)时 |
| 为HTTP Request节点配置认证(Bearer、基础认证、OAuth、头部认证)时 |
| 用户提及了你不了解的服务时 |
Anti-patterns
反模式
| Anti-pattern | What goes wrong | Fix |
|---|---|---|
Pasting | Token in plain text in the workflow JSON, leaks on export, copy, screenshot | Use a credential: |
| Storing token in a Set node and referencing via expression | Same problem, value lives in workflow JSON | Same fix: credential, not a Set node |
Storing a secret in | Not encrypted at rest, leaks in exports, no rotation | Use the right credential type ( |
Reaching for | Doesn't work, throws at runtime | Use a credential of the appropriate type |
| Using HTTP Request when a native node exists | Loses auto-refresh on OAuth, loses native error handling, more code | Use the native node |
Hardcoding credentials in SDK code ( | Same leak surface | Use |
| Asking the user to create a credential without naming the credential type | User picks the wrong type, auth fails confusingly | Always specify: "create a credential of type |
| 反模式 | 问题所在 | 修复方案 |
|---|---|---|
将 | 令牌以明文形式存在于工作流JSON中,导出、复制、截图时会泄露 | 使用凭证:Bearer令牌用 |
| 将令牌存储在Set节点中并通过表达式引用 | 相同问题,值仍存在于工作流JSON中 | 相同修复方案:使用凭证,而非Set节点 |
将机密存储在 | 存储时未加密,导出时会泄露,无法轮换 | 使用正确的凭证类型( |
在自定义认证设置中通过 | 运行时会报错 | 使用对应类型的凭证 |
| 存在原生节点时仍使用HTTP Request节点 | 失去OAuth自动刷新功能、原生错误处理能力,需要编写更多代码 | 使用原生节点 |
在SDK代码中硬编码凭证( | 存在相同的泄露风险 | 在SDK代码中使用 |
| 要求用户创建凭证但未指定凭证类型 | 用户可能选错类型,导致认证失败且难以排查 | 始终明确指定:“创建类型为 |