OAuth令牌管理系统(Airtable存储)
高级
这是一个Engineering领域的自动化工作流,包含 20 个节点。主要使用 If, Code, Webhook, Airtable, HttpRequest 等节点。 OAuth令牌管理系统(Airtable存储)
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •Airtable API Key
- •可能需要目标 API 的认证凭证
分类
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "2e491e733aabd347ba9dbe351de2eb0282b95dd5f327bc32034e70bc5642d897"
},
"nodes": [
{
"id": "1529173e-b4ae-4352-a378-a327c39e7fed",
"name": "成功",
"type": "n8n-nodes-base.if",
"position": [
448,
-48
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "faa449f2-815c-41fa-8378-e93093ad10d7",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.success }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "140b3700-3721-4e41-b87c-8df70e995bc4",
"name": "验证失败",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
672,
48
],
"parameters": {
"options": {
"responseCode": 401
},
"respondWith": "json",
"responseBody": "={\n \"success\": false,\n \"error\": \"{{ $('validator').first().json.reason }}\"\n}"
},
"typeVersion": 1.4
},
{
"id": "4715c17e-56d8-49f5-bcce-7f5b6f822f49",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
592,
-304
],
"parameters": {
"color": 6,
"width": 260,
"height": 308,
"content": "## 数据库示例"
},
"typeVersion": 1
},
{
"id": "722d92c2-445c-4c0a-9e06-a58dbc075907",
"name": "密钥验证",
"type": "n8n-nodes-base.if",
"position": [
1120,
-240
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "2e4151fc-f513-4a1d-8e42-c77857de22bc",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.secret }}",
"rightValue": "={{ $('client receiver').item.json.body.client_secret }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a02e3055-eb51-4fec-a429-d8349e388fe4",
"name": "无效客户端",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1120,
-48
],
"parameters": {
"options": {
"responseCode": 400
},
"respondWith": "json",
"responseBody": "{\n\"success\": false,\n\"error\": \"Invalid client id\"\n}"
},
"typeVersion": 1.1
},
{
"id": "729d6799-6f74-457c-aac5-ca651e10f170",
"name": "无效密钥",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1344,
-144
],
"parameters": {
"options": {
"responseCode": 401
},
"respondWith": "json",
"responseBody": "{\n\"success\": false,\n\"error\": \"Invalid client secret\"\n}"
},
"typeVersion": 1.1
},
{
"id": "b94ab331-23c2-473d-afdc-e591b89b38e0",
"name": "生成令牌",
"type": "n8n-nodes-base.code",
"position": [
1344,
-336
],
"parameters": {
"jsCode": "function generateLongToken(length) {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let token = '';\n for (let i = 0; i < length; i++) {\n token += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return token;\n}\n\nconst token = generateLongToken(32);\n\nreturn [\n {\n json: {\n token\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "204e04af-34a7-4824-b107-4cc3e89199e3",
"name": "客户端存在",
"type": "n8n-nodes-base.if",
"position": [
896,
-144
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "6f16470a-aae4-4647-850e-332284b00a9f",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.id }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e366461a-ece5-47d1-b5de-ea29aa1846ca",
"name": "验证器",
"type": "n8n-nodes-base.code",
"position": [
224,
-48
],
"parameters": {
"jsCode": "const input = $json;\n\nconst body = input.body || {};\n\n// Allowed keys\nconst allowedKeys = ['client_id', 'client_secret'];\n\n// Check required keys\nfor (const key of allowedKeys) {\n if (!body.hasOwnProperty(key)) {\n return [{ json: { success: false, reason: `Missing '${key}' in body` } }];\n }\n}\n\n// Check for extra keys\nconst extraKeys = Object.keys(body).filter(k => !allowedKeys.includes(k));\nif (extraKeys.length > 0) {\n return [{ json: { success: false, reason: `Body must contain only 'client_id' and 'client_secret', found extra key(s): ${extraKeys.join(', ')}` } }];\n}\n\n// All good\nreturn [{ json: { success: true } }];"
},
"typeVersion": 2
},
{
"id": "b7ea9e5f-d097-4ff7-b165-ee1560bb054d",
"name": "客户端接收器",
"type": "n8n-nodes-base.webhook",
"position": [
0,
-48
],
"webhookId": "e502851b-c6a5-4de2-94c7-c2320c73f203",
"parameters": {
"path": "token-refresher",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "70e09e1b-336a-4756-af23-aa4a0636e854",
"name": "获取客户端ID",
"type": "n8n-nodes-base.airtable",
"position": [
672,
-144
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appbw5TEhn8xIxxXR",
"cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR",
"cachedResultName": "Testing Bearer Auth "
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblK2jv4hLOsaKM3m",
"cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR/tblK2jv4hLOsaKM3m",
"cachedResultName": "Client IDs"
},
"options": {},
"operation": "search",
"filterByFormula": "={client} = \"{{ $('client receiver').item.json.body.client_id }}\""
},
"credentials": {
"airtableTokenApi": {
"id": "SCfOTbIrHHSfAWgr",
"name": "Testing Bearer Auth "
}
},
"typeVersion": 2.1,
"alwaysOutputData": true
},
{
"id": "d5c9d779-5805-45a0-affd-a683a17391ac",
"name": "创建令牌",
"type": "n8n-nodes-base.airtable",
"position": [
1568,
-336
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appbw5TEhn8xIxxXR",
"cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR",
"cachedResultName": "Testing Bearer Auth "
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblnqvjl4U2t9OMQD",
"cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR/tblnqvjl4U2t9OMQD",
"cachedResultName": "Tokens"
},
"columns": {
"value": {
"Token ID": "={{ $json.token }}",
"Client IDs": "={{ [$('client receiver').item.json.body.client_id] }}",
"Token Type": "Bearer",
"Creation Date": "={{ $now }}"
},
"schema": [
{
"id": "Token ID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Token ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Token Type",
"type": "options",
"display": true,
"options": [
{
"name": "Bearer",
"value": "Bearer"
}
],
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Token Type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Expiration Date",
"type": "dateTime",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Expiration Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Issued To",
"type": "array",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Issued To",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Creation Date",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Creation Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Is Active",
"type": "boolean",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Is Active",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Days Until Expiration",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "Days Until Expiration",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Client IDs",
"type": "array",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Client IDs",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"typecast": true
},
"operation": "create"
},
"credentials": {
"airtableTokenApi": {
"id": "SCfOTbIrHHSfAWgr",
"name": "Testing Bearer Auth "
}
},
"typeVersion": 2.1,
"alwaysOutputData": true
},
{
"id": "09da5fce-3635-4125-903b-a55ca93a5b4b",
"name": "响应",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1792,
-336
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={\n \"access_token\": \"{{ $('generate token').item.json.token }}\",\n \"expires_in\": 3600,\n \"token_type\": \"{{ $json.fields['Token Type'] }}\"\n}"
},
"typeVersion": 1.2
},
{
"id": "325443c4-31b4-472f-ab2c-e606776466ba",
"name": "其他方法",
"type": "n8n-nodes-base.webhook",
"position": [
0,
272
],
"webhookId": "3a898a00-f298-4d47-b1d0-26d2eb6d1898",
"parameters": {
"path": "test-jobs",
"options": {},
"httpMethod": [
"DELETE",
"HEAD",
"PATCH",
"PUT",
"GET"
],
"responseMode": "responseNode",
"multipleMethods": true
},
"typeVersion": 2
},
{
"id": "8b407e94-1e92-4882-872f-f6b2e6e60673",
"name": "405 错误",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
208,
320
],
"parameters": {
"options": {
"responseCode": 405
},
"respondWith": "json",
"responseBody": "{\n \"error\": \"Use POST request instead\"\n}"
},
"typeVersion": 1.1
},
{
"id": "7bc3accc-791d-4f8a-8f14-80f2d3d4ddf9",
"name": "点击\"执行工作流\"时",
"type": "n8n-nodes-base.manualTrigger",
"position": [
16,
-448
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d94ffe0e-95f7-459c-a837-a08b9ac3d87f",
"name": "发起请求",
"type": "n8n-nodes-base.httpRequest",
"position": [
240,
-448
],
"parameters": {
"url": "https://localhost:8080/webhook/token-refresher",
"method": "POST",
"options": {},
"jsonBody": "{\n \"client_id\": \"client_a_1234567890abcdef\",\n \"client_secret\": \"secret_a_abcdef1234567890\"\n\n}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.2
},
{
"id": "b9ea6991-ba49-49f0-bffb-5cc807eedb94",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
-512
],
"parameters": {
"color": 7,
"width": 460,
"height": 220,
"content": "## 测试请求"
},
"typeVersion": 1
},
{
"id": "e8814551-20d1-4114-b691-0a45cbf61086",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
208
],
"parameters": {
"color": 7,
"width": 460,
"height": 280,
"content": "## HTTP 方法处理器"
},
"typeVersion": 1
},
{
"id": "db9c1b3f-00ba-40fe-8e9c-f900be065940",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-688,
-512
],
"parameters": {
"color": 4,
"width": 580,
"height": 1656,
"content": "## OAuth 令牌生成器和验证器"
},
"typeVersion": 1
}
],
"pinData": {
"client receiver": [
{
"body": {
"client_id": "client_a_1234567890abcdef",
"client_secret": "secret_a_abcdef1234567890"
},
"query": {},
"params": {},
"headers": {
"host": "api.hirempire.com",
"accept": "*/*",
"x-real-ip": "102.190.108.154",
"user-agent": "PostmanRuntime/7.44.1",
"content-type": "application/json",
"cache-control": "no-cache",
"postman-token": "d4f91538-8577-4892-98fe-e58cdf6279d5",
"content-length": "103",
"accept-encoding": "gzip, deflate, br",
"x-forwarded-for": "102.190.108.154",
"x-forwarded-host": "api.hirempire.com",
"x-forwarded-port": "443",
"x-forwarded-proto": "https",
"x-forwarded-server": "483fb0fb5aec"
},
"webhookUrl": "https://api.hirempire.com/v1/token-refresher",
"executionMode": "production"
}
]
},
"connections": {
"success": {
"main": [
[
{
"node": "get client id",
"type": "main",
"index": 0
}
],
[
{
"node": "validation failed",
"type": "main",
"index": 0
}
]
]
},
"validator": {
"main": [
[
{
"node": "success",
"type": "main",
"index": 0
}
]
]
},
"create token": {
"main": [
[
{
"node": "respond ",
"type": "main",
"index": 0
}
]
]
},
"Other methods": {
"main": [
[
{
"node": "405 Error",
"type": "main",
"index": 0
}
],
[
{
"node": "405 Error",
"type": "main",
"index": 0
}
],
[
{
"node": "405 Error",
"type": "main",
"index": 0
}
],
[
{
"node": "405 Error",
"type": "main",
"index": 0
}
],
[
{
"node": "405 Error",
"type": "main",
"index": 0
}
]
]
},
"client exists": {
"main": [
[
{
"node": "secret validation",
"type": "main",
"index": 0
}
],
[
{
"node": "invalid client",
"type": "main",
"index": 0
}
]
]
},
"get client id": {
"main": [
[
{
"node": "client exists",
"type": "main",
"index": 0
}
]
]
},
"generate token": {
"main": [
[
{
"node": "create token",
"type": "main",
"index": 0
}
]
]
},
"client receiver": {
"main": [
[
{
"node": "validator",
"type": "main",
"index": 0
}
]
]
},
"secret validation": {
"main": [
[
{
"node": "generate token",
"type": "main",
"index": 0
}
],
[
{
"node": "invalid secret",
"type": "main",
"index": 0
}
]
]
},
"When clicking ‘Execute workflow’": {
"main": [
[
{
"node": "Make a request",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 工程
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用Bearer令牌认证和Airtable验证API请求
使用Bearer令牌认证和Airtable验证API请求
If
Code
Webhook
+5
24 节点Nazmy
工程
备份工作流到 GitHub(子文件夹)
备份工作流到 GitHub(子文件夹)
If
N8n
Set
+12
25 节点Nazmy
其他
CSV到JSON转换器(错误处理与Slack通知)
具有错误处理和Slack通知功能的CSV到JSON转换器
If
Set
Code
+8
18 节点n8n Team
工程
PUQ Docker NextCloud 部署
部署 Docker NextCloud,WHMCS/WISECP 的 API 后端
If
Set
Ssh
+6
44 节点PUQcloud
工程
获取所有Scaleway服务器信息副本
通过动态筛选获取Scaleway服务器信息
If
Set
Code
+7
24 节点Pablo
工程
OpenAI响应API适配器 - LLM与AI智能体工作流
面向LLM和AI智能体工作流的OpenAI响应API适配器
If
Code
Webhook
+6
19 节点Jimleuk
工程