Authenticating Todoist Webhook Requests

For anyone trying to figure out how to authenticate Todoist’s webhook requests, I thought I’d share my findings.

Jumping to the Point
Use the crypto node to JSON stringify the raw values from the Todoist node’s body object. This can be compared to the hmac in the webhook request headers.

Example of how to JSON stringify the raw values:
{{JSON.stringify($node["Todoist Node"].json["body"])}}
(Change “Todoist Node” to the name of your todoist node)

Details
As Todoist’s documentation explains, a webhook request’s X-Todoist-Hmac-SHA256 header can be compared to authenticate the source of the request. Simply generate a SHA256 Hmac of the entire request payload encoded in base64 and compare.

To do so, use the Crypto node. Settings are as follows:
Action: Hmac
Type: SHA256
Value: {{JSON.stringify($node[“Name of Your Todoist Node”].json[“body”])}}
Secret: Your Todoist client secret
Encoding: BASE64

The resulting output can be compared with the X-Todoist-Hmac-SHA256 header Todoist has provided with the request.

Example workflow provided here

Thanks for sharing @San

1 Like

Hope it’s helpful!

Here’s an example workflow in case anyone can use it:

{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "todoist",
        "options": {}
      },
      "name": "Todoist Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        450,
        320
      ],
      "webhookId": "5076b20d-431d-4dd2-9a9a-d3a9fea1c018"
    },
    {
      "parameters": {
        "action": "hmac",
        "type": "SHA256",
        "value": "={{JSON.stringify($node[\"Todoist Webhook\"].json[\"body\"])}}",
        "secret": "0000000000000000000000000000",
        "encoding": "base64"
      },
      "name": "Webhook Authenticator",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 1,
      "position": [
        630,
        320
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"Webhook Authenticator\"].json[\"data\"]}}",
              "value2": "={{$node[\"Todoist Webhook\"].json[\"headers\"][\"x-todoist-hmac-sha256\"]}}"
            }
          ]
        }
      },
      "name": "Request is Authentic",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        820,
        320
      ]
    },
    {
      "parameters": {},
      "name": "Take some action",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1070,
        260
      ]
    }
  ],
  "connections": {
    "Todoist Webhook": {
      "main": [
        [
          {
            "node": "Webhook Authenticator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Authenticator": {
      "main": [
        [
          {
            "node": "Request is Authentic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Request is Authentic": {
      "main": [
        [
          {
            "node": "Take some action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
1 Like