AutomationFlowsGeneral › Verify Slack Webhook Signature

Verify Slack Webhook Signature

Original n8n title: Slack Webhook - Verify Signature

Slack Webhook - Verify Signature. Uses crypto, stopAndError, executeWorkflowTrigger, stickyNote. Event-driven trigger; 12 nodes.

Event trigger★★★★☆ complexity12 nodesCryptoStop And ErrorExecute Workflow Trigger
General Trigger: Event Nodes: 12 Complexity: ★★★★☆ Added:

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "84dT8cFL0FV8ZGPx",
  "name": "Slack Webhook - Verify Signature",
  "tags": [],
  "nodes": [
    {
      "id": "b12fe8e7-45c4-4021-826e-3ae430e34001",
      "name": "Make Slack Verif Token",
      "type": "n8n-nodes-base.code",
      "position": [
        900,
        400
      ],
      "parameters": {
        "jsCode": "function encodeFormData(data) {\n  const encodedData = Object.keys(data)\n    .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))\n    .join('&')\n    .replaceAll(\"%20\", \"+\") // Slack does not encode \"+\" signs\n    .replaceAll(\"*\", \"%2A\") // Slack encodes \"*\" signs\n    .replaceAll(\"~\", \"%7E\"); // Slack encodes \"~\" signs\n    \n  return encodedData;\n}\n\nfunction buildSigBaseString(requestJson) {\n  const version = \"v0\"; // Slack Webhook version (Always v0 for the moment)\n  \n  const timestamp = requestJson.headers[\"x-slack-request-timestamp\"];\n  \n  const body = requestJson.body;\n  const encodedBody = encodeFormData(body);\n  \n  const sigBaseString = `${version}:${timestamp}:${encodedBody}`;\n\n  return sigBaseString;\n}\n\nconst requestJson = $input.first().json;\n\nconst sigBaseString = buildSigBaseString(requestJson);\n\nconst requestSignature = requestJson.headers[\"x-slack-signature\"];\n\nconsole.log({\n    sigBaseString,\n    requestSignature\n  });\nreturn {\n  json: {\n    sigBaseString,\n    requestSignature\n  },\n  pairedItem: 0\n}\n\n\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a91e2d8f-e907-439c-9fd3-cb75e957b059",
      "name": "Encode Secret String",
      "type": "n8n-nodes-base.crypto",
      "position": [
        1120,
        400
      ],
      "parameters": {
        "type": "SHA256",
        "value": "={{ $json.sigBaseString }}",
        "action": "hmac",
        "dataPropertyName": "candidateSignature"
      },
      "typeVersion": 1
    },
    {
      "id": "d79ccfe1-61cd-4da4-bfff-1e504627bb3d",
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "position": [
        1360,
        400
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.requestSignature }}",
              "value2": "=v0={{ $json.candidateSignature }}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cb2b9908-c226-438b-adb2-7c1ec852e007",
      "name": "Stop and Error",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        1580,
        580
      ],
      "parameters": {
        "errorMessage": "Could not verify Slack Webhook signature"
      },
      "typeVersion": 1
    },
    {
      "id": "5ef4c06a-717b-4f90-83a7-06eda780a892",
      "name": "Execute Workflow Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        680,
        400
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "86b022fb-63fd-4ccf-952e-19ed0da54a5c",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -420
      ],
      "parameters": {
        "color": 4,
        "width": 554.4117841902089,
        "height": 278.2403290971726,
        "content": "## Slack Webhook - Verify Signature \nWhen receiving a message from a Slack Webhook, it is much more secure to verify that the message comes from Slack and not from bots or unknown services.\n\nThis small template is designed to validate the received signature (See [this URL](https://api.slack.com/authentication/verifying-requests-from-slack)).\n\n### Colors\n- **Blue** areas are **areas to edit**\n- **Yellow** areas are **explanations**"
      },
      "typeVersion": 1
    },
    {
      "id": "f5af4f44-1ea5-419b-a58b-f8f6839b6b05",
      "name": "Set Verified to True",
      "type": "n8n-nodes-base.set",
      "position": [
        1580,
        220
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "signature_verified",
              "type": "booleanValue"
            }
          ]
        },
        "include": "none",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "8a76dec8-7a2d-4cc9-82c9-002141e205ec",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1920,
        40
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "mergeByPosition"
      },
      "typeVersion": 2.1
    },
    {
      "id": "0c8506bc-b114-4d25-8586-80549ae0026d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1000,
        40
      ],
      "parameters": {
        "color": 6,
        "width": 359.58396920054975,
        "height": 548.3119898759418,
        "content": "## TO EDIT \nSet your Slack Signing Secret.\nYou can obtain it by visiting your Slack App dashboard in the general tab: https://api.slack.com/apps/[SLACK_APP_ID]/general\n"
      },
      "typeVersion": 1
    },
    {
      "id": "20cca69c-9d00-4471-8845-2cb91458c23e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1560,
        399
      ],
      "parameters": {
        "width": 300.4638046519632,
        "height": 360.20237540316725,
        "content": "## Error Output\nIf the signature cannot be verified, an error will be raised. You can manage this scenario in your main workflow by either using an Error Workflow or by modifying your node settings and selecting appropriate actions in the event of an error.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "55ede23b-acb4-43ea-ac32-c678dd48e056",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1880,
        -220
      ],
      "parameters": {
        "width": 300.4638046519632,
        "height": 427.3843805720155,
        "content": "## Success Output\nIf the signature is successfully verified, we return a key `verified_signature` set to `true` along with the data from the Slack request itself.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "22d44888-5af4-43b9-b514-ebfc9c61b07c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        160
      ],
      "parameters": {
        "width": 300.4638046519632,
        "height": 427.3843805720155,
        "content": "## Input\nThe input should be the received Slack request. Place this workflow directly after the Slack Webhook.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f9e78d89-0da8-465e-aa47-5396d9ac4d48",
  "connections": {
    "IF": {
      "main": [
        [
          {
            "node": "Set Verified to True",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop and Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Encode Secret String": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Verified to True": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Make Slack Verif Token": {
      "main": [
        [
          {
            "node": "Encode Secret String",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Workflow Trigger": {
      "main": [
        [
          {
            "node": "Make Slack Verif Token",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

How this works

Secure your Slack integrations by automatically verifying incoming webhook signatures to prevent unauthorised access and ensure data integrity, giving you peace of mind that only legitimate requests from Slack are processed. This workflow is ideal for developers and teams building custom automations that receive Slack webhooks, such as notifications or commands, without needing deep cryptographic expertise. The key step involves using the crypto node to compute a signature from your Slack app's signing secret and comparing it against the incoming header, halting execution if they mismatch to block potential attacks.

Use this workflow whenever you handle sensitive Slack webhooks in production environments, like syncing messages to databases or triggering actions in tools such as Google Sheets. Avoid it for non-webhook triggers or low-security testing setups where signature verification adds unnecessary overhead. Common variations include extending it with the executeWorkflowTrigger node to chain into broader automations, or adapting the IF node logic for custom validation rules.

About this workflow

Slack Webhook - Verify Signature. Uses crypto, stopAndError, executeWorkflowTrigger, stickyNote. Event-driven trigger; 12 nodes.

Source: https://github.com/Zie619/n8n-workflows — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

General

Generate Leads with Google Maps - AlexK1919. Uses manualTrigger, scheduleTrigger, executeWorkflowTrigger, stopAndError. Event-driven trigger; 42 nodes.

Execute Workflow Trigger, Stop And Error, HTTP Request +1
General

Stopanderror. Uses manualTrigger, stickyNote, executeWorkflowTrigger, nextCloud. Event-driven trigger; 32 nodes.

Execute Workflow Trigger, Next Cloud, Stop And Error
General

airflow dag_run. Uses httpRequest, stopAndError, executeWorkflowTrigger. Event-driven trigger; 12 nodes.

HTTP Request, Stop And Error, Execute Workflow Trigger
General

Post on X. Uses airtop, executeWorkflowTrigger, formTrigger, stopAndError. Event-driven trigger; 10 nodes.

Airtop, Execute Workflow Trigger, Form Trigger +1
General

Http Stickynote. Uses httpRequest, executeWorkflowTrigger, stickyNote, sendInBlue. Event-driven trigger; 22 nodes.

HTTP Request, Execute Workflow Trigger, Sendinblue