Skip to content

Commit 8bdb969

Browse files
add http verify hmac signature
1 parent b733d83 commit 8bdb969

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import crypto from "crypto";
2+
3+
export default {
4+
name: "Verify HMAC Signature",
5+
version: "0.0.1",
6+
key: "http-verify-hmac-signature",
7+
description: "Validate HMAC signature for incoming HTTP webhook requests. Make sure to configure the HTTP trigger to \"Return a custom response from your workflow\".",
8+
type: "action",
9+
props: {
10+
http: "$.interface.http",
11+
secret: {
12+
type: "string",
13+
label: "Secret",
14+
description: "Your secret key used for validation",
15+
secret: true,
16+
},
17+
signature: {
18+
type: "string",
19+
label: "Signature",
20+
description: "The HMAC signature received from the incoming webhook, typically provided in a specific HTTP header",
21+
},
22+
bodyRaw: {
23+
type: "string",
24+
label: "Raw Body",
25+
description: "The raw request body received from the webhook caller, provided as a string without any parsing or modifications",
26+
},
27+
customResponse: {
28+
type: "boolean",
29+
label: "Return Error to Webhook Caller",
30+
description: "If `True`, returns a `401: Invalid credentials` error in the case of invalid authorization. **Make sure to configure the HTTP trigger to \"Return a custom response from your workflow\"**. If `False`, does not return a custom response in the case of invalid auth.",
31+
default: true,
32+
},
33+
},
34+
methods: {
35+
_checkHmac(secret, signature, bodyRaw) {
36+
const expectedSignature = crypto
37+
.createHmac("sha256", secret)
38+
.update(bodyRaw, "utf8")
39+
.digest();
40+
41+
const signatureBuffer = Buffer.from(signature, "hex");
42+
if (signatureBuffer.length !== expectedSignature.length) {
43+
return false;
44+
}
45+
return crypto.timingSafeEqual(signatureBuffer, expectedSignature);
46+
},
47+
},
48+
async run({ $ }) {
49+
const valid = this._checkHmac(
50+
this.secret,
51+
this.signature,
52+
this.bodyRaw,
53+
);
54+
55+
if (!valid) {
56+
if (this.customResponse) {
57+
await $.respond({
58+
status: 401,
59+
headers: {},
60+
body: "Invalid credentials",
61+
});
62+
}
63+
return $.flow.exit("Invalid credentials");
64+
}
65+
66+
$.export("$summary", "HTTP request successfully authenticated");
67+
},
68+
};

0 commit comments

Comments
 (0)