DEV Community

Joseph D. Marhee
Joseph D. Marhee

Posted on • Originally published at Medium on

Validating Phone Numbers before making a Twilio Call with Flask

A couple weeks ago, I wrote about building a tool to make browser-based called to Congress using Twilio. A feature I had not yet implemented, but a useful one now that the app is online and potentially a target for someone trying to make calls to someone other than members of Congress (which uses up valuable compute resources and Twilio funds, which can impact the experience others may have using the app!) — the ability to validate the calls are going to who they say they are.

The way the app works is that you enter your zip code, and it returns, typically, a dialer object for your two US Senators and your US House Representative. So, for example, for 33026, it return Senators Rick Scott and Marco Rubio, and Congresswoman Debbie Wasserman-Schultz.

This data is generated, in our example, from a JSON object called representatives which contains this information:

{'name': name, 'office': office, 'phone': phone, 'unformatted_phone': unformatted_phone, 'urls': urls, 'party': party, 'photo': photo, 'p_phone': p_phone, 'p_unformatted_phone': p_unformatted_phone}
Enter fullscreen mode Exit fullscreen mode

which the front-end, when it receive this data based on your submitted zip code on the home page, generates the page above with the Start and Hangup buttons to control the call.

On the front-end template, you’ve already POST -d your zip code, and it receives the representatives object, and then for each representative, it generates the dialer like this:

<button class='f5 f4-ns dim dib mtl br2 bg-white-10 ba b-red-40 blue-80 link pam call call-customer-button' onclick="params = { 'PhoneNumber': 'number:{{ **phone\_number** }}', 'zipCode': 'zipCode:{{ **zipCode** }}' }; Twilio.Device.connect(params);">

Start Call

</button>
Enter fullscreen mode Exit fullscreen mode

So, the problem is, then, if someone wanted to make a call to some other number, they could, inspect the element on the page, and update this value to whatever they wanted.

and on the backend, when you clicked the button, it would get passed to the function which actually connects the browser to Twilio, and then callback to the app to open the connection:

So, when your Twilio app callsback to to Flask, it will simply pick out the number from the POST data, and then hand it to the dial.number() function. This is not ideal if your project is cash strapped, making a lot of calls (so your refill rate is high), or you think it may become a target for misuse. So, my solution was to implement a function that I’d written, but didn’t employ initially:

which takes the zipCode from the callback’s POST request, and the phone number it attempted to dial, and if that number is found, it will re-confirm the phone number in the response along with a status of OK . Otherwise, it only returns an indicator that it was an invalid phone number.

Using this function is pretty straightforward:

Basically, rather than proceeding to dial the number, we check if numberVerify() returns an OK status, and then verifies the number once more before dialing.

If it returns an empty status for an invalid number, it dials my callback TwiML application, the number set in NUMBERS_OUTBOUND, which (for the ease of congressional staffers, perhaps wondering why so many people are calling from single number) just explains who is calling and why (constituents using a free service to reach their representative!).

Top comments (0)