Skip to content

Commit ec1f9f0

Browse files
authored
Merge pull request #17 from aymenn/basic-auth
Add basic auth to sessions route and webhook validation to other routes
2 parents be6d4d9 + 2aab6ec commit ec1f9f0

File tree

6 files changed

+2077
-19
lines changed

6 files changed

+2077
-19
lines changed

.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ CALL_ANNOUCEMENT_VOICE=
55
CALL_ANNOUCEMENT_LANGUAGE=
66
OUT_OF_SESSION_MESSAGE_FOR_CALL=
77
CONNECTING_CALL_ANNOUCEMENT=
8-
DOMAIN=
8+
DOMAIN=
9+
AUTH_USERNAME=
10+
AUTH_PASSWORD=

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ $ cp .env.example .env
5151
| CALL_ANNOUCEMENT_LANGUAGE | The language to speak announcements in. | "en" or any of the [supported languages](https://www.twilio.com/docs/voice/twiml/say#attributes-language). |
5252
| OUT_OF_SESSION_MESSAGE_FOR_CALL | A message to play if someone calls the number pool without an active session. | "Your session is no longer active. Goodbye." |
5353
| CONNECTING_CALL_ANNOUCEMENT | A message to play when a caller is being connected to the other party. | "We're connecting you to your agent now." |
54-
| DOMAIN | The domain where the application will be hosted. | "mysite.com" or "https://your-domain.ngrok.io" |
55-
54+
| DOMAIN | The domain where the application will be hosted. | "mysite.com" or "your-domain.ngrok.io" (no https://) |
55+
| AUTH_USERNAME | Basic auth username for request authorization | "mySecureUserName" |
56+
| AUTH_PASSWORD | Basic auth password for request authorization | "mySecretPassword" |
5657

5758
Once you have your environment variables set, you can start the app with this command:
5859

@@ -85,6 +86,10 @@ Two webhooks can be configured in the Twilio Console:
8586
- Paste your webhook (`https://[your-domain]/conversations-post-event`) into the Post-Event URL input box.
8687
- Click "save" at the bottom of the page.
8788

89+
# Authentication & Webhook Validation
90+
The app requires basic auth on request to the `/sessions` endpoint. This prevents an unauthorized person from creating sessions. To use basic auth, make sure `DOMAIN` (e.g. mysite.com, no http://), `AUTH_USERNAME`, and `AUTH_PASSWORD` are all set in your .env file, and restart the app.
91+
92+
Webhooks are automatically validated using the Twilio Webhook signature. This prevents an unauthorized request to start a phone call without your permission. For webhook validation to work, your app needs `DOMAIN` to be set along with `TWILIO_AUTH_TOKEN` in the .env file.
8893

8994
# Usage
9095
You can create a new masked-number session between multiple users by making a post request to the `/sessions` endpoint:
@@ -146,4 +151,4 @@ To conduct a load test on the app, run:
146151
```bash
147152
$ yarn loadtest
148153
```
149-
This will generate 300 conversations in 20ms intervals against the app.
154+
This will generate 300 conversations in 20ms intervals against the app.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"cors": "^2.8.5",
66
"dotenv": "^16.0.1",
77
"express": "^4.18.1",
8+
"express-basic-auth": "^1.2.1",
89
"http-errors": "^2.0.0",
910
"morgan": "^1.10.0",
1011
"twilio": "^3.78.0"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function shouldValidate () {
2+
return process.env.NODE_ENV !== 'test'
3+
}
4+
5+
export const webhookConfig = {
6+
protocol: 'https',
7+
host: process.env.DOMAIN,
8+
validate: shouldValidate()
9+
}

src/routes/index.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
import { Router } from "express";
22
import * as controllers from "../controllers";
33

4+
import twilio from 'twilio'
5+
import { webhookConfig } from '../config/webhookValidationConfig'
6+
7+
import basicAuth from 'express-basic-auth'
8+
const { AUTH_USERNAME, AUTH_PASSWORD } = process.env
9+
410
const router = Router();
511

6-
router.post("/conversations-post-event", controllers.conversationsPostEvent.post);
12+
router.post("/conversations-post-event", twilio.webhook(webhookConfig), controllers.conversationsPostEvent.post);
713

8-
router.post("/inbound-call", controllers.inboundCall.post);
9-
router.get("/join-conference", controllers.joinConference.get)
14+
router.post("/inbound-call", twilio.webhook(webhookConfig), controllers.inboundCall.post);
15+
router.post("/join-conference", twilio.webhook(webhookConfig), controllers.joinConference.get)
1016

11-
router.post("/sessions", controllers.session.post);
17+
router.post("/sessions", basicAuth({
18+
users: { [AUTH_USERNAME]:AUTH_PASSWORD}
19+
}), controllers.session.post);
1220

1321
export default router;

0 commit comments

Comments
 (0)