Slack Signature Verification (#2667)
* Slack Verify * Adding await * Update slackVerify.ts Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> Co-authored-by: zomars <zomars@me.com>
This commit is contained in:
parent
02b935bcde
commit
fa1ca5fba0
3 changed files with 40 additions and 1 deletions
|
@ -2,6 +2,7 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
|||
|
||||
import { showCreateEventMessage, showTodayMessage } from "../lib";
|
||||
import showLinksMessage from "../lib/showLinksMessage";
|
||||
import slackVerify from "../lib/slackVerify";
|
||||
|
||||
export enum SlackAppCommands {
|
||||
CREATE_EVENT = "create-event",
|
||||
|
@ -12,7 +13,7 @@ export enum SlackAppCommands {
|
|||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method === "POST") {
|
||||
const command = req.body.command.split("/").pop();
|
||||
|
||||
await slackVerify(req, res);
|
||||
switch (command) {
|
||||
case SlackAppCommands.CREATE_EVENT:
|
||||
return await showCreateEventMessage(req, res);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import createEvent from "../lib/actions/createEvent";
|
||||
import slackVerify from "../lib/slackVerify";
|
||||
|
||||
enum InteractionEvents {
|
||||
CREATE_EVENT = "cal.event.create",
|
||||
|
@ -8,6 +9,7 @@ enum InteractionEvents {
|
|||
|
||||
export default async function interactiveHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method === "POST") {
|
||||
await slackVerify(req, res);
|
||||
const payload = JSON.parse(req.body.payload);
|
||||
const actions = payload.view.callback_id;
|
||||
|
||||
|
|
36
packages/app-store/slackmessaging/lib/slackVerify.ts
Normal file
36
packages/app-store/slackmessaging/lib/slackVerify.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { createHmac } from "crypto";
|
||||
import dayjs from "dayjs";
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { stringify } from "querystring";
|
||||
|
||||
import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";
|
||||
|
||||
let signingSecret = "";
|
||||
|
||||
export default async function slackVerify(req: NextApiRequest, res: NextApiResponse) {
|
||||
const body = req.body;
|
||||
const timeStamp = req.headers["x-slack-request-timestamp"] as string; // Always returns a string and not a string[]
|
||||
const slackSignature = req.headers["x-slack-signature"] as string;
|
||||
const currentTime = dayjs().unix();
|
||||
let { signing_secret } = await getAppKeysFromSlug("slack");
|
||||
if (typeof signing_secret === "string") signingSecret = signing_secret;
|
||||
|
||||
if (!timeStamp) {
|
||||
return res.status(400).json({ message: "Missing X-Slack-Request-Timestamp header" });
|
||||
}
|
||||
|
||||
if (!signingSecret) {
|
||||
return res.status(400).json({ message: "Missing Slack's signing_secret" });
|
||||
}
|
||||
|
||||
if (Math.abs(currentTime - parseInt(timeStamp)) > 60 * 5) {
|
||||
return res.status(400).json({ message: "Request is too old" });
|
||||
}
|
||||
|
||||
const signature_base = `v0:${timeStamp}:${stringify(body)}`;
|
||||
const signed_sig = "v0=" + createHmac("sha256", signingSecret).update(signature_base).digest("hex");
|
||||
|
||||
if (signed_sig !== slackSignature) {
|
||||
return res.status(400).json({ message: "Invalid signature" });
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue