Skip to content

Commit

Permalink
misc: add referer checker and csp header (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
embbnux authored Jul 8, 2024
1 parent 80bad06 commit 6e31207
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const subscriptionRoute = require('./routes/subscription');
const { botHandler } = require('./bot/handler');
const { botConfig } = require('./bot/config');
const { errorLogger } = require('./utils/logger');
const { refererChecker } = require('./utils/refererChecker');

const app = express()
app.use(morgan(function (tokens, req, res) {
Expand Down Expand Up @@ -36,7 +37,7 @@ app.post('/notify/:id', notificationRoute.notification);
app.post('/notify_v2/:id', notificationRoute.notification);

app.get('/webhook/new', subscriptionRoute.setup);
app.post('/webhooks', subscriptionRoute.createWebhook);
app.post('/webhooks', refererChecker, subscriptionRoute.createWebhook);

app.post('/interactive-messages', notificationRoute.interactiveMessages);

Expand Down
2 changes: 2 additions & 0 deletions src/server/routes/subscription.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ async function setup(req, res) {
res.send('Webhook uri is required.');
return;
}
const IFRAME_HOST_DOMAINS = "https://*.ringcentral.com https://*.ringcentral.biz https://*.glip.com https://*.glip.net https://glip.com https://*.labs.ringcentral.com http://*.integration.ringcentral.com http://*.devtest.ringcentral.com https://*.unifyoffice.com https://*.officeathand.att.com https://*.cloudoffice.avaya.com https://*.cloudwork.bt.com https://*.rainbowoffice.com https://*.businessconnect.telus.com https://*.vodafonebusiness.ringcentral.com";
res.set('Content-Security-Policy', `frame-ancestors 'self' ${IFRAME_HOST_DOMAINS};`);
res.render('new', {
glipWebhookUri,
analyticsKey: process.env.MIXPANEL_KEY,
Expand Down
35 changes: 35 additions & 0 deletions src/server/utils/refererChecker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
function getOrigin(uri) {
if (!uri) {
return null;
}
const url = new URL(uri);
return url.origin;
}

const KNOWN_REFERER_HOSTS = [
getOrigin(process.env.APP_SERVER),
getOrigin(process.env.RINGCENTRAL_CHATBOT_SERVER),
];

function refererChecker(req, res, next) {
const referrer = req.get('Referer');
if (!referrer) {
res.status(403).send('No Referer');
return;
}
const referrerOrigin = getOrigin(referrer);
if (
KNOWN_REFERER_HOSTS.find(host => {
if (!host) {
return false;
}
return host === referrerOrigin;
})
) {
next();
return;
}
res.status(403).send('Invalid Referer');
};

exports.refererChecker = refererChecker;
2 changes: 1 addition & 1 deletion tests/notify.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('Notify', () => {
let bugsnagWebhookRecord;

beforeAll(async () => {
await request(server).post('/webhooks').send({ webhook });
await request(server).post('/webhooks').send({ webhook }).set('Referer', process.env.APP_SERVER);
const rcWebhookRecord = await RCWebhook.findByPk(webhookId);
bugsnagWebhookRecord = await Webhook.findByPk(rcWebhookRecord.bugsnag_webhook_id);
});
Expand Down
21 changes: 18 additions & 3 deletions tests/webhook.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,34 @@ describe('Webhook new', () => {
it('should get new webhook page successfully', async () => {
const res = await request(server).get('/webhook/new?webhook=http://test.com/webhook_id');
expect(res.status).toEqual(200);
expect(res.header['content-security-policy']).toContain("frame-ancestors 'self'");
});
});

describe('Webhook generate', () => {
it('should get 400 without webhook uri', async () => {
it('should get 403 without referer', async () => {
const res = await request(server).post('/webhooks');
expect(res.status).toEqual(403);
expect(res.text).toEqual('No Referer');
});

it('should get 403 with wrong referer', async () => {
const res = await request(server)
.post('/webhooks')
.set('Referer', 'http://test.com');
expect(res.status).toEqual(403);
expect(res.text).toEqual('Invalid Referer');
});

it('should get 400 without webhook uri', async () => {
const res = await request(server).post('/webhooks').set('Referer', process.env.APP_SERVER);
expect(res.status).toEqual(400);
});

it('should generate webhook successfully', async () => {
const webhookId = 'webhook_id';
const webhook = `http://test.com/${webhookId}`;
const res = await request(server).post('/webhooks').send({ webhook });
const res = await request(server).post('/webhooks').send({ webhook }).set('Referer', process.env.APP_SERVER);
expect(res.status).toEqual(200);
const webhookUri = res.body.webhookUri;
const rcWebhookRecord = await RCWebhook.findByPk(webhookId);
Expand All @@ -37,7 +52,7 @@ describe('Webhook generate', () => {
const webhookId = 'webhook_id';
const webhook = `http://test.com/${webhookId}`;
const existedRCWebhookRecord = await RCWebhook.findByPk(webhookId);
const res = await request(server).post('/webhooks').send({ webhook });
const res = await request(server).post('/webhooks').send({ webhook }).set('Referer', process.env.APP_SERVER);
expect(res.status).toEqual(200);
const webhookUri = res.body.webhookUri;
expect(`${process.env.APP_SERVER}/notify/${existedRCWebhookRecord.bugsnag_webhook_id}`).toEqual(webhookUri);
Expand Down

0 comments on commit 6e31207

Please sign in to comment.