Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Twilio authentication always fails #715

Open
hklchung opened this issue Jun 6, 2023 · 6 comments
Open

Twilio authentication always fails #715

hklchung opened this issue Jun 6, 2023 · 6 comments
Labels
status: help wanted requesting help from the community type: question question directed at the library

Comments

@hklchung
Copy link

hklchung commented Jun 6, 2023

Issue Summary

I am developing a Python (Flask) voice app on a local machine and using Ngrok tunnel to allow Twilio access the app via a webhook (all set up according to the Twilio guide). I need to add a step to check the requests are coming from Twilio and am using the RequestValidator from the Twilio Python SDK. However, this step always returns false, but should be true as I am the one initiating the request during testing.

Steps to Reproduce

  1. Set up a test voice application with Python Flask, and using Ngrok tunnel
  2. Get the host, request url and scope
  3. Run RequestValidator()

Code Snippet

In your Python Flask test voice application, set up a /call app route, then inside the call() test the following

validator = RequestValidator(TWILIO_AUTH_TOKEN)

path = request.path
headers = dict(request.headers)
host = headers.get('Host')
url = f"http://{host}{path}"
body = request.data

validator.validate(request.url, headers, body)

Technical details:

  • twilio-python version: 8.1.0
  • python version: 3.8.8
  • Flask version: 2.2.2
  • pyngrok version: 6.0.0
@charan678
Copy link

Hello @hklchung Can you please refer this end-end test link? Let me know if this helps.

@charan678
Copy link

@hklchung did you use this guide ?

@hklchung
Copy link
Author

hklchung commented Jun 7, 2023

@hklchung did you use this guide ?

Hi @charan678 this is the guide I have been following. I have also double checked to ensure the Twilio webhook URL starts with http:// since I am using Ngrok.

I tried to run test_url() but unfortunately all returned with a response code 404.

Any advice on how to proceed would be highly appreciated
111
.
222

@charan678
Copy link

hello @hklchung It's working for me. Following are the steps followed by me

  1. setup ngrok
  • run ngrok config command ( ngrok config add-authtoken XXXXXXXXX). here XXXXXX is your ngrok authToken
  • run ngrok http command (ngrok --scheme http http 5000)
  1. open active phone number page and add ngrok http url to webhook for both messaging and voice

  2. I used this code below to test and export TWILIO_AUTH_TOKEN before running in local env

from flask import Flask, request, abort
from twilio.twiml.voice_response import VoiceResponse
from twilio.twiml.messaging_response import MessagingResponse
from twilio.request_validator import RequestValidator
from functools import wraps
import os


app = Flask(__name__)

def validate_twilio_request(f):
    """Validates that incoming requests genuinely originated from Twilio"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        # Create an instance of the RequestValidator class
        validator = RequestValidator(os.environ.get('TWILIO_AUTH_TOKEN'))

        # Validate the request using its URL, POST data,
        # and X-TWILIO-SIGNATURE header
        request_valid = validator.validate(
            request.url,
            request.form,
            request.headers.get('X-TWILIO-SIGNATURE', ''))

        print("Request valid = ", request_valid)
        # Continue processing the request if it's valid, return a 403 error if
        # it's not
        if request_valid:
            return f(*args, **kwargs)
        else:
            return abort(403)
    return decorated_function


@app.route('/voice', methods=['POST'])
@validate_twilio_request
def incoming_call():
    """Twilio Voice URL - receives incoming calls from Twilio"""
    # Create a new TwiML response
    resp = VoiceResponse()

    # <Say> a message to the caller
    from_number = request.values['From']
    body = """
    Thanks for calling!

    Your phone number is {0}. I got your call because of Twilio's webhook.

    Goodbye!""".format(' '.join(from_number))
    resp.say(body)

    # Return the TwiML
    return str(resp)

#
@app.route('/message', methods=['POST'])
@validate_twilio_request
def incoming_message():
    """Twilio Messaging URL - receives incoming messages from Twilio"""
    # Create a new TwiML response
    resp = MessagingResponse()

    # <Message> a text back to the person who texted us
    body = "Your text to me was {0} characters long. Webhooks are neat :)" \
        .format(len(request.values['Body']))
    resp.message(body)

    # Return the TwiML
    return str(resp)

@app.route('/health', methods=['GET'])
def healthcheck():
    return str("received")

if __name__ == '__main__':
    app.run(debug=True)
  • check your flask server is running on 5000 port
  1. Call on your active phone number and see the flask logs
  • Its displaying 200 status code and request valid True for me

Technical Details

twilio-python = 8.1.0
python version = 3.8.8
os = mac os
Test phone number location = us ( +1 XXX )
Flask version = 2.2.2

refer:

How to Use Ngrok to Send Automatic Textback SMS Using POST & GET API Requests
how-to-secure-your-flask-app-by-validating-incoming-twilio-requests

@hklchung
Copy link
Author

hklchung commented Jun 8, 2023

Thanks @charan678, your answer provided me new direction to test in a more granular level. I found a working solution.

The webhook on the Twilio console must first be set to http://, Ngrok tunnels can have both http:// and https:// (no need to change anything here). But the tricky part is when the request comes through to the app, the request URL is of course a http://, this needs to be manually changed back to https:// before sending into the RequestValidator().

Would you know why this change is required, considering the webhook URL set in the console is http:// and not a https://?

@AsabuHere AsabuHere added type: question question directed at the library status: help wanted requesting help from the community labels Jul 5, 2023
@joshkulick
Copy link

Please check out my solution that I introduced issues, This was super frustrating in having to debug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: help wanted requesting help from the community type: question question directed at the library
Projects
None yet
Development

No branches or pull requests

4 participants