twilio-node icon indicating copy to clipboard operation
twilio-node copied to clipboard

twilio.webhook() returning unauthorized although TWILIO_AUTH_TOKEN is set

Open gborobio73 opened this issue 9 months ago • 2 comments

Hello, we are using the twilio.webhook() as described in here https://www.twilio.com/docs/usage/tutorials/how-to-secure-your-express-app-by-validating-incoming-twilio-requests#use-twilio-express-request-validation-middleware.

The code we are running is exactly like this:

// index.ts 
import express, { Request, Response } from 'express';
import twilio from 'twilio';
import bodyParser from 'body-parser';
import VoiceResponse from 'twilio/lib/twiml/VoiceResponse';
import MessagingResponse from 'twilio/lib/twiml/MessagingResponse';

const shouldValidate = process.env.NODE_ENV !== 'test';
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));

app.post('/api/call', twilio.webhook({ validate: shouldValidate }), (req: Request, res: Response) => {
  // Twilio Voice URL - receives incoming calls from Twilio
  console.log('Call received; greeting the caller');
  const response = new VoiceResponse();

  response.say(
    `Thanks for calling!
     Your phone number is ${req.body.From}. I got your call because of Twilio´s
     webhook. Goodbye!`
  );

  res.set('Content-Type', 'text/xml');
  res.send(response.toString());
});

app.post(
  '/message',
  twilio.webhook({ validate: shouldValidate }),
  (req: Request, res: Response) => {
    // Twilio Messaging URL - receives incoming messages from Twilio
    const response = new MessagingResponse();

    response.message(`Your text to me was ${req.body.Body
      .length} characters long.
                    Webhooks are neat :)`);

    res.set('Content-Type', 'text/xml');
    res.send(response.toString());
  }
);
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});

But we can see in the logs that the call results in unauthorized:

2025-03-24T15:06:05.720895+00:00: at=info method=POST path="/api/call" host=<edited> request_id=<edited> fwd="<edited>" service=3ms status=403 bytes=241 protocol=https

The TWILIO_AUTH_TOKEN is set, and it's the one from the Twilio console.

Is there anything else that we are missing?

Thank you!

gborobio73 avatar Mar 24 '25 15:03 gborobio73

But, this approach works https://www.twilio.com/en-us/blog/how-to-secure-twilio-webhook-urls-in-nodejs using exactly the same code.

gborobio73 avatar Mar 24 '25 15:03 gborobio73

It's good you narrowed this down to a working code version vs. one that's not working.

If you can edit the twilio-node code inside your node_modules directory - could you verify that twilio.validateRequest is being called with the same arguments in both cases? In the blog post demo, it's being called with a protocol and host that I'm not sure you are getting from your Express app.

kevinburke avatar Apr 08 '25 13:04 kevinburke

Closing this issue since there are no updates in last 30 days. Thanks!

tiwarishubham635 avatar Jun 23 '25 06:06 tiwarishubham635