Skip to content

Commit

Permalink
#3044 challenge handshake and event verification
Browse files Browse the repository at this point in the history
  • Loading branch information
chpy04 committed Dec 13, 2024
1 parent d919f32 commit 6b8863e
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/backend/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import workPackageTemplatesRouter from './src/routes/work-package-templates.rout
import carsRouter from './src/routes/cars.routes';
import organizationRouter from './src/routes/organizations.routes';
import recruitmentRouter from './src/routes/recruitment.routes';
import slackRouter from './src/routes/slack.routes';

const app = express();
const port = process.env.PORT || 3001;
Expand Down Expand Up @@ -67,6 +68,7 @@ app.use('/templates', workPackageTemplatesRouter);
app.use('/cars', carsRouter);
app.use('/organizations', organizationRouter);
app.use('/recruitment', recruitmentRouter);
app.use('/slack', slackRouter);
app.use('/', (_req, res) => {
res.json('Welcome to FinishLine');
});
Expand Down
42 changes: 42 additions & 0 deletions src/backend/src/controllers/slack.controllers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Request, Response } from 'express';
import crypto from 'crypto';
import slackServices from '../services/slack.services';

export default class slackController {
static async handleEvent(req: Request, res: Response) {
console.log('got a slack req');
if (req.body.type === 'url_verification') {
return res.status(200).send({ challenge: req.body.challenge });
}

const slackSignature = req.headers['x-slack-signature'] as string;
const slackTimeStamp = req.headers['X-Slack-Request-Timestamp'] as string;

if (Math.abs(Date.now() - Number(slackTimeStamp) * 1000) > 60 * 5 * 1000) {
return res.status(400).send('Slack request verification failed due to expired timestamp');
}

const reqBody = req.body;

const signatureBase = 'v0:' + slackTimeStamp + ':' + reqBody;

const finalSignature =
'v0=' +
crypto
.createHmac('sha256', process.env.SLACK_BOT_TOKEN ? process.env.SLACK_BOT_TOKEN : '')
.update(signatureBase)
.digest('hex');

if (
crypto.timingSafeEqual(
Uint8Array.from(Buffer.from(finalSignature, 'utf8')),
Uint8Array.from(Buffer.from(slackSignature, 'utf8'))
)
) {
slackServices.processEvent(req.body);
return res.status(200).send('Event recieved');
}

return res.status(400).send('Slack request verification failed due to incorrect signature');
}
}
8 changes: 8 additions & 0 deletions src/backend/src/routes/slack.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import express from 'express';
import slackController from '../controllers/slack.controllers';

const slackRouter = express.Router();

slackRouter.post('/', slackController.handleEvent);

export default slackRouter;
6 changes: 6 additions & 0 deletions src/backend/src/services/slack.services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default class slackServices {
static async processEvent(req: any ) {
//TODO: process request
console.log(req);
}
}
9 changes: 6 additions & 3 deletions src/backend/src/utils/auth.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export const requireJwtProd = (req: Request, res: Response, next: NextFunction)
if (
req.path === '/users/auth/login' || // logins dont have cookies yet
req.path === '/' || // base route is available so aws can listen and check the health
req.method === 'OPTIONS' // this is a pre-flight request and those don't send cookies
req.method === 'OPTIONS' || // this is a pre-flight request and those don't send cookies
req.path === '/slack' // slack http endpoint is only used from slack api
) {
return next();
} else if (
Expand Down Expand Up @@ -62,7 +63,8 @@ export const requireJwtDev = (req: Request, res: Response, next: NextFunction) =
req.path === '/users/auth/login/dev' || // logins dont have cookies yet
req.path === '/' || // base route is available so aws can listen and check the health
req.method === 'OPTIONS' || // this is a pre-flight request and those don't send cookies
req.path === '/users' // dev login needs the list of users to log in
req.path === '/users' || // dev login needs the list of users to log in
req.path === '/slack' // slack http endpoint is only used from slack api
) {
next();
} else if (
Expand Down Expand Up @@ -171,7 +173,8 @@ export const getUserAndOrganization = async (req: Request, res: Response, next:
req.path === '/users/auth/login/dev' ||
req.path === '/' || // base route is available so aws can listen and check the health
req.method === 'OPTIONS' || // this is a pre-flight request and those don't send cookies
req.path === '/users' // dev login needs the list of users to log in
req.path === '/users' || // dev login needs the list of users to log in
req.path === '/slack' // slack http endpoint is only used from slack api
) {
return next();
}
Expand Down

0 comments on commit 6b8863e

Please sign in to comment.