Пример #1
0
    def decorated_function(*args, **kwargs):
        # Create an instance of the RequestValidator class
        validator = RequestValidator(app.config['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', '')
        )

        # Some services, like Glitch or ngrok, don't maintain the `https` scheme
        # when proxying requests to our app. So if the request seemed invalid
        # on our first try, try again with an https version of the URL
        if not request_valid:
            request_valid = validator.validate(
                request.url.replace('http://', 'https://'),
                request.form,
                request.headers.get('X-TWILIO-SIGNATURE', '')
            )

        # Continue processing the request if it's valid (or we're in development
        # or testing). Otherwise, return a 403 error if it's not
        if request_valid or app.config['TESTING']
            return f(*args, **kwargs)
        else:
            return abort(403)
Пример #2
0
    def decorated_function(*args, **kwargs):
        # Create an instance of the RequestValidator class
        validator = RequestValidator(tw_auth_token)
        # validator = RequestValidator(tw_api_secret)

        # Validate the request using its URL, POST data,
        # and X_TWILIO_SIGNATURE header
        logging.info(request.url)
        if not ('ngrok' in str(request.url)):
            request_valid = validator.validate(
                str(request.url).replace('http', 'https'), request.form,
                request.headers.get('X-TWILIO-SIGNATURE', ''))
        else:
            request_valid = validator.validate(
                # str(request.url),
                str(request.url).replace('http', 'https'),
                request.form,
                request.headers.get('X-TWILIO-SIGNATURE', ''))

        # Continue processing the request if it's valid,
        # return a 403 error if it's not
        if request_valid:
            return f(*args, **kwargs)
        else:
            logging.warning("Signature invalid")
            logging.info(request.url)
            logging.info(request.headers)
            return abort(403)
Пример #3
0
class ValidationTest(unittest.TestCase):
    def setUp(self):
        token = "12345"
        self.validator = RequestValidator(token)

        self.uri = "https://mycompany.com/myapp.php?foo=1&bar=2"
        self.params = {
            "CallSid": "CA1234567890ABCDE",
            "Digits": "1234",
            "From": "+14158675309",
            "To": "+18005551212",
            "Caller": "+14158675309",
        }
        self.expected = "RSOYDt4T1cUTdK1PDd93/VVr8B8="
        self.body = "{\"property\": \"value\", \"boolean\": true}"
        self.bodyHash = "Ch/3Y02as7ldtcmi3+lBbkFQKyg6gMfPGWMmMvluZiA="
        self.encodedBodyHash = self.bodyHash.replace("+", "%2B").replace(
            "=", "%3D")
        self.uriWithBody = self.uri + "&bodySHA256=" + self.encodedBodyHash

    def test_compute_signature_bytecode(self):
        expected = b(self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=False)
        assert_equal(signature, expected)

    def test_compute_signature_unicode(self):
        expected = u(self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=True)
        assert_equal(signature, expected)

    def test_compute_hash_bytecode(self):
        expected = b(self.bodyHash)
        body_hash = self.validator.compute_hash(self.body, utf=False)

        assert_equal(expected, body_hash)

    def test_compute_hash_unicode(self):
        expected = u(self.bodyHash)
        body_hash = self.validator.compute_hash(self.body, utf=True)

        assert_equal(expected, body_hash)

    def test_validation(self):
        assert_true(
            self.validator.validate(self.uri, self.params, self.expected))

    def test_validation_removes_port_on_https(self):
        uri = self.uri.replace(".com", ".com:1234")
        assert_true(self.validator.validate(uri, self.params, self.expected))

    def test_validation_of_body_succeeds(self):
        uri = self.uriWithBody
        is_valid = self.validator.validate(uri, self.body,
                                           "afcFvPLPYT8mg/JyIVkdnqQKa2s=")
        assert_true(is_valid)
Пример #4
0
class ValidationTest(unittest.TestCase):

    def setUp(self):
        token = "1c892n40nd03kdnc0112slzkl3091j20"
        self.validator = RequestValidator(token)

        self.uri = "http://www.postbin.org/1ed898x"
        self.params = {
            "AccountSid": "AC9a9f9392lad99kla0sklakjs90j092j3",
            "ApiVersion": "2010-04-01",
            "CallSid": "CAd800bb12c0426a7ea4230e492fef2a4f",
            "CallStatus": "ringing",
            "Called": "+15306384866",
            "CalledCity": "OAKLAND",
            "CalledCountry": "US",
            "CalledState": "CA",
            "CalledZip": "94612",
            "Caller": "+15306666666",
            "CallerCity": "SOUTH LAKE TAHOE",
            "CallerCountry": "US",
            "CallerName": "CA Wireless Call",
            "CallerState": "CA",
            "CallerZip": "89449",
            "Direction": "inbound",
            "From": "+15306666666",
            "FromCity": "SOUTH LAKE TAHOE",
            "FromCountry": "US",
            "FromState": "CA",
            "FromZip": "89449",
            "To": "+15306384866",
            "ToCity": "OAKLAND",
            "ToCountry": "US",
            "ToState": "CA",
            "ToZip": "94612",
        }

    def test_compute_signature_bytecode(self):
        expected = b("fF+xx6dTinOaCdZ0aIeNkHr/ZAA=")
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=False)
        assert_equal(signature, expected)

    def test_compute_signature_unicode(self):
        expected = u("fF+xx6dTinOaCdZ0aIeNkHr/ZAA=")
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=True)
        assert_equal(signature, expected)

    def test_validation(self):
        expected = "fF+xx6dTinOaCdZ0aIeNkHr/ZAA="
        assert_true(self.validator.validate(self.uri, self.params, expected))

    def test_validation_removes_port_on_https(self):
        self.uri = "https://www.postbin.org:1234/1ed898x"
        expected = "Y7MeICc5ECftd1G11Fc8qoxAn0A="
        assert_true(self.validator.validate(self.uri, self.params, expected))
Пример #5
0
    def decorator(request_or_self, *args, **kwargs):
        # When using `method_decorator` on class methods,
        # I haven't been able to get any class views.
        # i would like more research before just taking the check out.
        class_based_view = not isinstance(request_or_self, HttpRequest)
        if not class_based_view:
            request = request_or_self
        else:
            assert len(args) >= 1
            request = args[0]

        # Turn off Twilio authentication when explicitly requested, or
        # in debug mode. Otherwise things do not work properly. For
        # more information, see the docs.
        use_forgery_protection = getattr(
            settings,
            'DJANGO_TWILIO_FORGERY_PROTECTION',
            not settings.DEBUG,
        )
        if use_forgery_protection:

            if request.method not in ['GET', 'POST']:
                return HttpResponseNotAllowed(request.method)

            # Forgery check
            try:
                validator = RequestValidator(TWILIO_AUTH_TOKEN)
                url = request.build_absolute_uri()
                signature = request.META['HTTP_X_TWILIO_SIGNATURE']
            except (AttributeError, KeyError):
                return HttpResponseForbidden()

            if request.method == 'POST':
                if not validator.validate(url, request.POST, signature):
                    return HttpResponseForbidden()
            if request.method == 'GET':
                if not validator.validate(url, request.GET, signature):
                    return HttpResponseForbidden()

        # Blacklist check, by default is true
        check_blacklist = getattr(
            settings,
            'DJANGO_TWILIO_BLACKLIST_CHECK',
            True
        )
        if check_blacklist:
            blacklisted_resp = get_blacklisted_response(request)
            if blacklisted_resp:
                return blacklisted_resp

        response = f(request_or_self, *args, **kwargs)

        if isinstance(response, (text_type, bytes)):
            return HttpResponse(response, content_type='application/xml')
        elif isinstance(response, Verb):
            return HttpResponse(str(response), content_type='application/xml')
        else:
            return response
class ValidationTest(unittest.TestCase):
    def setUp(self):
        token = "1c892n40nd03kdnc0112slzkl3091j20"
        self.validator = RequestValidator(token)

        self.uri = "http://www.postbin.org/1ed898x"
        self.params = {
            "AccountSid": "AC9a9f9392lad99kla0sklakjs90j092j3",
            "ApiVersion": "2010-04-01",
            "CallSid": "CAd800bb12c0426a7ea4230e492fef2a4f",
            "CallStatus": "ringing",
            "Called": "+15306384866",
            "CalledCity": "OAKLAND",
            "CalledCountry": "US",
            "CalledState": "CA",
            "CalledZip": "94612",
            "Caller": "+15306666666",
            "CallerCity": "SOUTH LAKE TAHOE",
            "CallerCountry": "US",
            "CallerName": "CA Wireless Call",
            "CallerState": "CA",
            "CallerZip": "89449",
            "Direction": "inbound",
            "From": "+15306666666",
            "FromCity": "SOUTH LAKE TAHOE",
            "FromCountry": "US",
            "FromState": "CA",
            "FromZip": "89449",
            "To": "+15306384866",
            "ToCity": "OAKLAND",
            "ToCountry": "US",
            "ToState": "CA",
            "ToZip": "94612",
        }

    def test_compute_signature_bytecode(self):
        expected = b("fF+xx6dTinOaCdZ0aIeNkHr/ZAA=")
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=False)
        assert_equal(signature, expected)

    def test_compute_signature_unicode(self):
        expected = u("fF+xx6dTinOaCdZ0aIeNkHr/ZAA=")
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=True)
        assert_equal(signature, expected)

    def test_validation(self):
        expected = "fF+xx6dTinOaCdZ0aIeNkHr/ZAA="
        assert_true(self.validator.validate(self.uri, self.params, expected))

    def test_validation_removes_port_on_https(self):
        self.uri = "https://www.postbin.org:1234/1ed898x"
        expected = "Y7MeICc5ECftd1G11Fc8qoxAn0A="
        assert_true(self.validator.validate(self.uri, self.params, expected))
class ValidationTest(unittest.TestCase):

    def setUp(self):
        token = "12345"
        self.validator = RequestValidator(token)

        self.uri = "https://mycompany.com/myapp.php?foo=1&bar=2"
        self.params = {
            "CallSid": "CA1234567890ABCDE",
            "Digits": "1234",
            "From": "+14158675309",
            "To": "+18005551212",
            "Caller": "+14158675309",
        }
        self.expected = "RSOYDt4T1cUTdK1PDd93/VVr8B8="
        self.body = "{\"property\": \"value\", \"boolean\": true}"
        self.bodyHash = "Ch/3Y02as7ldtcmi3+lBbkFQKyg6gMfPGWMmMvluZiA="
        self.encodedBodyHash = self.bodyHash.replace("+", "%2B").replace("=", "%3D")
        self.uriWithBody = self.uri + "&bodySHA256=" + self.encodedBodyHash

    def test_compute_signature_bytecode(self):
        expected = b(self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=False)
        assert_equal(signature, expected)

    def test_compute_signature_unicode(self):
        expected = u(self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=True)
        assert_equal(signature, expected)

    def test_compute_hash_bytecode(self):
        expected = b(self.bodyHash)
        body_hash = self.validator.compute_hash(self.body, utf=False)

        assert_equal(expected, body_hash)

    def test_compute_hash_unicode(self):
        expected = u(self.bodyHash)
        body_hash = self.validator.compute_hash(self.body, utf=True)

        assert_equal(expected, body_hash)

    def test_validation(self):
        assert_true(self.validator.validate(self.uri, self.params, self.expected))

    def test_validation_removes_port_on_https(self):
        uri = self.uri.replace(".com", ".com:1234")
        assert_true(self.validator.validate(uri, self.params, self.expected))

    def test_validation_of_body_succeeds(self):
        uri = self.uriWithBody
        is_valid = self.validator.validate(uri, self.body, "afcFvPLPYT8mg/JyIVkdnqQKa2s=")
        assert_true(is_valid)
def validate(request, url):
    request_meta_data = dict()
    validator = RequestValidator(token)
    print(url)
    url = url + "/" + "sms"
    for key_item in request.form:
        request_meta_data[key_item] = request.form[key_item]
    twilio_signature = request.headers.get("X-Twilio-Signature", None)
    print(twilio_signature)
    print(request_meta_data)
    print(validator.validate(url, request_meta_data, twilio_signature))
    return (validator.validate(url, request_meta_data, twilio_signature))
Пример #9
0
class ValidationTest(unittest.TestCase):
    def setUp(self):
        token = "12345"
        self.validator = RequestValidator(token)

        self.uri = "https://mycompany.com/myapp.php?foo=1&bar=2"
        self.params = {
            "CallSid": "CA1234567890ABCDE",
            "Digits": "1234",
            "From": "+14158675309",
            "To": "+18005551212",
            "Caller": "+14158675309",
        }
        self.expected = "RSOYDt4T1cUTdK1PDd93/VVr8B8="
        self.body = "{\"property\": \"value\", \"boolean\": true}"
        self.bodyHash = "0a1ff7634d9ab3b95db5c9a2dfe9416e41502b283a80c7cf19632632f96e6620"
        self.uriWithBody = self.uri + "&bodySHA256=" + self.bodyHash

    def test_compute_signature_bytecode(self):
        expected = b(self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=False)
        assert_equal(signature, expected)

    def test_compute_signature(self):
        expected = (self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=True)
        assert_equal(signature, expected)

    def test_compute_hash_unicode(self):
        expected = u(self.bodyHash)
        body_hash = self.validator.compute_hash(self.body)

        assert_equal(expected, body_hash)

    def test_validation(self):
        assert_true(
            self.validator.validate(self.uri, self.params, self.expected))

    def test_validation_removes_port_on_https(self):
        uri = self.uri.replace(".com", ".com:1234")
        assert_true(self.validator.validate(uri, self.params, self.expected))

    def test_validation_of_body_succeeds(self):
        uri = self.uriWithBody
        is_valid = self.validator.validate(uri, self.body,
                                           "a9nBmqA0ju/hNViExpshrM61xv4=")
        assert_true(is_valid)
Пример #10
0
class ValidationTest(unittest.TestCase):

    def setUp(self):
        token = "12345"
        self.validator = RequestValidator(token)

        self.uri = "https://mycompany.com/myapp.php?foo=1&bar=2"
        self.params = {
            "CallSid": "CA1234567890ABCDE",
            "Digits": "1234",
            "From": "+14158675309",
            "To": "+18005551212",
            "Caller": "+14158675309",
        }
        self.expected = "RSOYDt4T1cUTdK1PDd93/VVr8B8="
        self.body = "{\"property\": \"value\", \"boolean\": true}"
        self.bodyHash = "0a1ff7634d9ab3b95db5c9a2dfe9416e41502b283a80c7cf19632632f96e6620"
        self.uriWithBody = self.uri + "&bodySHA256=" + self.bodyHash

    def test_compute_signature_bytecode(self):
        expected = b(self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=False)
        assert_equal(signature, expected)

    def test_compute_signature(self):
        expected = (self.expected)
        signature = self.validator.compute_signature(self.uri,
                                                     self.params,
                                                     utf=True)
        assert_equal(signature, expected)

    def test_compute_hash_unicode(self):
        expected = u(self.bodyHash)
        body_hash = self.validator.compute_hash(self.body)

        assert_equal(expected, body_hash)

    def test_validation(self):
        assert_true(self.validator.validate(self.uri, self.params, self.expected))

    def test_validation_removes_port_on_https(self):
        uri = self.uri.replace(".com", ".com:1234")
        assert_true(self.validator.validate(uri, self.params, self.expected))

    def test_validation_of_body_succeeds(self):
        uri = self.uriWithBody
        is_valid = self.validator.validate(uri, self.body, "a9nBmqA0ju/hNViExpshrM61xv4=")
        assert_true(is_valid)
Пример #11
0
def answeredby(request):
    # build validator manually because decorator not working
    logger.info(request.build_absolute_uri())
    twilio_request = decompose(request)
    validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)

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

    if not request_valid:
        return HttpResponseForbidden()

    outbound = Outbound.objects.get(twilio_sid=twilio_request.callsid)
    response = VoiceResponse()

    if twilio_request.answeredby in ['human', 'unknown']:
        response.play(outbound.action.audio_file.url)

    else:
        response.hangup()

    outbound.answered_by = twilio_request.answeredby
    outbound.save()

    return HttpResponse(response)
def lambda_handler(event, context):
    print("received: " + str(event))
    # if twilioSignature exists and message from authorized number, create a validator & a dictionary of received data
    if u'twilioSignature' in event and u'Body' in event and event[
            'From'] == os.environ['MY_NUMBER']:
        form_parameters = {
            key: urllib.parse.unquote_plus(value)
            for key, value in event.items() if key != u'twilioSignature'
        }

        validator = RequestValidator(os.environ['AUTH_TOKEN'])

        # validate api call is from twilio
        request_valid = validator.validate(os.environ['REQUEST_URL'],
                                           form_parameters,
                                           event[u'twilioSignature'])

        # if request valid, authenticate tweepy and send tweet
        if request_valid:
            auth = tweepy.OAuthHandler(os.environ['API_KEY'],
                                       os.environ['API_SECRET'])
            auth.set_access_token(os.environ['ACCESS_TOKEN'],
                                  os.environ['ACCESS_SECRET'])
            api = tweepy.API(auth)
            msg = form_parameters['Body']
            api.update_status(msg)

            return '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' \
                   '<Response><Message>Request Received, OK!</Message></Response>'

        # if request is not from twilio, give appropriate response
        else:
            return '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' \
                   '<Response><Message>Nice Try...</Message></Response>'
Пример #13
0
def twilio_webhook_handler(event, context):
    """Receive request from Twilio and passes through to a topic."""
    print("Received event: " + str(event))
    null_response = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' + \
                    '<Response></Response>'

    # Trap no X-Twilio-Signature Header
    if u'twilioSignature' not in event:
        return null_response

    form_parameters = {
        k: urllib.unquote_plus(v)
        for k, v in event.items() if k != u'twilioSignature'
    }

    validator = RequestValidator(os.environ['AUTH_TOKEN'])
    request_valid = validator.validate(os.environ['REQUEST_URL'],
                                       form_parameters,
                                       event[u'twilioSignature'])

    # Trap invalid requests not from Twilio
    if not request_valid:
        return null_response

    # Trap fields missing
    if u'Body' not in form_parameters or u'To' not in form_parameters \
            or u'From' not in form_parameters:
        return null_response

    # Don't let through messages with > 160 characters
    if len(form_parameters['Body']) > 160:
        return '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' + \
               '<Response><Message>Keep it under 160!</Message></Response>'

    # Now we package up the From, To, and Body field and publish it to the
    # 'twilio' topic (or whatever you have set).  Boto3 lets us easily publish
    # to any topic in a particular region, but ensure you have correctly set
    # permissions for the role.  'iot:Publish' needs to be included for these
    # next lines to work.

    aws_region = os.environ['AWS_IOT_REGION']
    aws_topic = os.environ['AWS_TOPIC']
    client = boto3.client('iot-data', region_name=aws_region)

    client.publish(topic=aws_topic,
                   qos=0,
                   payload=json.dumps({
                       "To": form_parameters[u'To'],
                       "From": form_parameters[u'From'],
                       "Body": form_parameters[u'Body'],
                       "Type": "Incoming"
                   }))

    # A blank response informs Twilio not to take any actions.
    # Since we are reacting asynchronously, if we are to respond
    # it will come through a different channel.
    #
    # Even though we aren't responding to the webhook directly, this will all
    # happen very quickly.
    return null_response
Пример #14
0
def sms_handler(request):
    """Entry point function for HTTP triggered Google Cloud Functions call.

    This function is triggered by a Twilio SMS webhook (POST).

    Args:
        - request (flask.Request): A Flask request.
    Returns:
        - (None)
    """
    firestore = init_firestore()

    # validate request from Twilio
    validator = RequestValidator(os.environ["TWILIO_AUTH_TOKEN"])
    request_valid = validator.validate(
        request.url, request.form, request.headers.get("X-TWILIO-SIGNATURE",
                                                       ""))

    if not request_valid:
        # request is not valid, do nothing
        print("request is not valid")
        return

    params = request.form
    body = params["Body"].lower().strip()

    if body == "no":
        add_unallowed_pair(firestore, params)
Пример #15
0
    def decorator(request, *args, **kwargs):
        # When using `method_decorator` on class methods,
        # I haven't been able to get any class views.
        # i would like more research before just taking the check out.

        # Forgery check
        try:
            validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
            url = request.build_absolute_uri()
            signature = request.META['HTTP_X_TWILIO_SIGNATURE']
        except (AttributeError, KeyError):
            return HttpResponseForbidden()

        if not validator.validate(url, request.POST, signature):
            return HttpResponseForbidden()

        # Blacklist check, by default is true
        # check_blacklist = getattr(
        #     settings,
        #     'DJANGO_TWILIO_BLACKLIST_CHECK',
        #     True
        # )
        # if check_blacklist:
        #     blacklisted_resp = get_blacklisted_response(request)
        #     if blacklisted_resp:
        #         return blacklisted_resp

        response = f(request, *args, **kwargs)
        return response
Пример #16
0
class TwilioClient:
    def __init__(self, account_sid, auth_token):
        self.client = Client(account_sid, auth_token)
        self.request_validator = RequestValidator(auth_token)

    def compute_signature(self, uri, params):
        """proxy twilio.RequestValidator.compute_signature()"""
        return self.request_validator.compute_signature(uri, params)

    def validate_request(self, uri, params, signature):
        """proxy twilio.RequestValidator.validate()"""
        return self.request_validator.validate(uri, params, signature)

    def send_sms(self, to="", from_="", body=""):
        try:
            message = self.client.messages.create(
                to=to,
                from_=from_,
                body=body
            )
        except TwilioRestException:
            # TODO log this original exception for debugging
            raise TwilioClientException('Failed to send SMS')

        return message
Пример #17
0
async def process_sms(request: Request,
                      From: str = Form(...),
                      Body: str = Form(...)):
    validator = RequestValidator(os.environ["TWILIO_AUTH_TOKEN"])
    form_ = await request.form()
    if not validator.validate(str(request.url), form_,
                              request.headers.get("X-Twilio-Signature", "")):
        raise HTTPException(status_code=400,
                            detail="Error in Twilio Signature")

    response = MessagingResponse()

    print(Body)

    vectorized_name = gender_cv.transform([Body]).toarray()
    prediction = gender_clf.predict(vectorized_name)
    if prediction[0] == 0:
        result = 'Female'
    else:
        result = 'Male'

    print(result)

    response.message(result)

    return Response(content=str(response), media_type="application/xml")
Пример #18
0
def fizzbuzzTWIML():
    response = VoiceResponse()

    validator = RequestValidator(TWILIO_AUTH_TOKEN)
    request_valid = validator.validate(
        request.url, request.form, request.headers.get('X-TWILIO-SIGNATURE',
                                                       ''))

    if not request_valid:
        response.say("Not a Twilio account")

    response.say("Starting now")

    number = int(request.form.get('Digits', ''))

    for i in range(1, number + 1):
        if i % 3 == 0 and i % 5 == 0:
            response.say("fizzbuzz.")
        elif i % 3 == 0:
            response.say("fizz.")
        elif i % 5 == 0:
            response.say("buzz.")
        else:
            string = str(i) + "."
            response.say(string)

    return str(response)
Пример #19
0
def protect_forged_request(request):
    if request.method not in ['GET', 'POST']:
        return HttpResponseNotAllowed(request.method)

    try:
        validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
        url = request.build_absolute_uri()
        signature = request.META['HTTP_X_TWILIO_SIGNATURE']
    except (AttributeError, KeyError):
        return HttpResponseForbidden()

    if request.method == 'POST':
        if not validator.validate(url, request.POST, signature):
            return HttpResponseForbidden()
    if request.method == 'GET':
        if not validator.validate(url, request.GET, signature):
            return HttpResponseForbidden()
Пример #20
0
def validate_twilio_request():
    validator = RequestValidator(auth_token)
    url = request.url[:4] + 's' + request.url[
        4:]  # add s because request comes in without it
    request_valid = validator.validate(
        url, request.form, request.headers.get('X-TWILIO-SIGNATURE', ''))
    if not request_valid:
        return abort(403)
Пример #21
0
def validate(request):
    validator = RequestValidator(os.environ.get('TWILIO_AUTH_TOKEN'))

    request_valid = validator.validate(
        URL, request.form, request.headers.get('X-Twilio-Signature', ''))

    if not request_valid:
        abort(403)
Пример #22
0
 def decorated_function(*args, **kwargs):
     validator = RequestValidator(twilio_token)
     request_valid = validator.validate(
         request.url, request.form,
         request.headers.get("X-TWILIO-SIGNATURE", ""))
     if request_valid:
         return f(*args, **kwargs)
     else:
         return abort(403)
Пример #23
0
def verify_twilio(request, app):

    # use twilio's docs on validating a request
    url = app.config.get('site_url')
    auth_token = app.config.get('auth_token')
    params = request.form
    validator = RequestValidator(auth_token)
    tw_sig = request.headers.get('X-Twilio-Signature')
    return (validator.validate(url, params, tw_sig))
Пример #24
0
def is_valid_twilio_request(request):
    twilio_request_validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
    request_path = request.build_absolute_uri(request.get_full_path()).replace(
        'http:', 'https:')
    # trailing slashes should be removed
    if request_path[-1] == '/':
        request_path = request_path[:-1]
    twilio_signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
    return twilio_request_validator.validate(request_path, request.POST,
                                             twilio_signature)
Пример #25
0
    def decorated_function(*args, **kwargs):
        validator = RequestValidator(app.config['TWILIO_AUTH_TOKEN'])
        request_valid = validator.validate(
            request.url, request.form,
            request.headers.get('X-TWILIO-SIGNATURE', ''))

        if request_valid:
            return f(*args, **kwargs)
        else:
            return abort(403)
Пример #26
0
def is_valid_twilio_request(request):
    twilio_request_validator = RequestValidator(settings.TWILIO_AUTH_TOKEN)
    request_path = request.build_absolute_uri(
        request.get_full_path()).replace('http:', 'https:')
    # trailing slashes should be removed
    if request_path[-1] == '/':
        request_path = request_path[:-1]
    twilio_signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
    return twilio_request_validator.validate(
            request_path, request.POST, twilio_signature)
Пример #27
0
    def authenticatesender(self, url, parameters, signature):

        if signature and url and parameters:

            validator = RequestValidator(self.auth_token)

            if validator.validate(url, parameters, signature):
                return True

        return False
    def decorated_function(*args, **kwargs):
        validator = RequestValidator(os.getenv('TWILIO_AUTH_TOKEN'))
        request_valid = validator.validate(
            request.url, request.form,
            request.headers.get('X-TWILIO-SIGNATURE', ''))

        if request_valid:
            return f(*args, **kwargs)
        else:
            return f'Sorry! This is not a valid request'
Пример #29
0
def receive_twilio_sms():
    response = MessagingResponse()

    auth = request.authorization

    if not auth:
        current_app.logger.warning("Inbound sms (Twilio) no auth header")
        abort(401)
    elif auth.username not in current_app.config[
            'TWILIO_INBOUND_SMS_USERNAMES'] or auth.password not in current_app.config[
                'TWILIO_INBOUND_SMS_PASSWORDS']:
        current_app.logger.warning(
            "Inbound sms (Twilio) incorrect username ({}) or password".format(
                auth.username))
        abort(403)

    # Locally, when using ngrok the URL comes in without HTTPS so force it
    # otherwise the Twilio signature validator will fail.
    url = request.url.replace("http://", "https://")
    post_data = request.form
    twilio_signature = request.headers.get('X-Twilio-Signature')

    validator = RequestValidator(os.getenv('TWILIO_AUTH_TOKEN'))

    if not validator.validate(url, post_data, twilio_signature):
        current_app.logger.warning(
            "Inbound sms (Twilio) signature did not match request")
        abort(400)

    service = fetch_potential_service(post_data['To'], 'twilio')

    if not service:
        # Since this is an issue with our service <-> number mapping, or no
        # inbound_sms service permission we should still tell Twilio that we
        # received it successfully.
        return str(response), 200

    statsd_client.incr('inbound.twilio.successful')

    inbound = create_inbound_sms_object(service,
                                        content=post_data["Body"],
                                        from_number=post_data['From'],
                                        provider_ref=post_data["MessageSid"],
                                        provider_name="twilio")

    tasks.send_inbound_sms_to_service.apply_async(
        [str(inbound.id), str(service.id)], queue=QueueNames.NOTIFY)

    current_app.logger.debug(
        '{} received inbound SMS with reference {} from Twilio'.format(
            service.id,
            inbound.provider_reference,
        ))

    return str(response), 200
Пример #30
0
def receive_twilio_sms():
    response = MessagingResponse()

    auth = request.authorization

    if not auth:
        current_app.logger.warning("Inbound sms (Twilio) no auth header")
        abort(401)
    elif auth.username not in current_app.config['TWILIO_INBOUND_SMS_USERNAMES'] \
            or auth.password not in current_app.config['TWILIO_INBOUND_SMS_PASSWORDS']:
        current_app.logger.warning(
            "Inbound sms (Twilio) incorrect username ({}) or password".format(
                auth.username))
        abort(403)

    url = request.url
    post_data = request.form
    twilio_signature = request.headers.get('X-Twilio-Signature')

    validator = RequestValidator(current_app.config['TWILIO_AUTH_TOKEN'])

    if not validator.validate(url, post_data, twilio_signature):
        current_app.logger.warning(
            "Inbound sms (Twilio) signature did not match request")
        abort(400)

    try:
        service = fetch_potential_service(post_data['To'], 'twilio')
    except NoSuitableServiceForInboundSms:
        # Since this is an issue with our service <-> number mapping, or no
        # inbound_sms service permission we should still tell Twilio that we
        # received it successfully.
        return str(response), 200

    statsd_client.incr('inbound.twilio.successful')

    inbound = create_inbound_sms_object(service,
                                        content=post_data["Body"],
                                        notify_number=post_data['To'],
                                        from_number=post_data['From'],
                                        provider_ref=post_data["MessageSid"],
                                        date_received=datetime.utcnow(),
                                        provider_name="twilio")

    send_inbound_sms_to_service.apply_async(
        [str(inbound.id), str(service.id)], queue=QueueNames.NOTIFY)

    current_app.logger.debug(
        '{} received inbound SMS with reference {} from Twilio'.format(
            service.id,
            inbound.provider_reference,
        ))

    return str(response), 200
Пример #31
0
    def decorated_function(*args, **kwargs):
        validator = RequestValidator(os.environ.get("TWILIO_AUTH_TOKEN"))

        request_valid = validator.validate(
            request.url, request.form,
            request.headers.get("X-TWILIO-SIGNATURE", ""))

        if request_valid:
            return f(*args, **kwargs)
        else:
            return abort(403)
Пример #32
0
    def decorator(request_or_self, *args, **kwargs):

        class_based_view = not isinstance(request_or_self, HttpRequest)
        if not class_based_view:
            request = request_or_self
        else:
            assert len(args) >= 1
            request = args[0]

        # Turn off Twilio authentication when explicitly requested, or
        # in debug mode. Otherwise things do not work properly. For
        # more information, see the docs.
        use_forgery_protection = getattr(
            settings,
            'DJANGO_TWILIO_FORGERY_PROTECTION',
            not settings.DEBUG,
        )
        if use_forgery_protection:

            if request.method not in ['GET', 'POST']:
                return HttpResponseNotAllowed(request.method)

            # Forgery check
            try:
                twilio_settings = SiteConfiguration.get_twilio_settings()
                validator = RequestValidator(twilio_settings['auth_token'])
                url = request.build_absolute_uri()
                signature = request.META['HTTP_X_TWILIO_SIGNATURE']
            except (AttributeError, KeyError, ConfigurationError):
                return HttpResponseForbidden()

            if request.method == 'POST':
                if not validator.validate(url, request.POST, signature):
                    return HttpResponseForbidden()
            if request.method == 'GET':
                if not validator.validate(url, request.GET, signature):
                    return HttpResponseForbidden()

        response = f(request_or_self, *args, **kwargs)

        return response
Пример #33
0
    def decorator(request_or_self, *args, **kwargs):

        class_based_view = not isinstance(request_or_self, HttpRequest)
        if not class_based_view:
            request = request_or_self
        else:
            assert len(args) >= 1
            request = args[0]

        # Turn off Twilio authentication when explicitly requested, or
        # in debug mode. Otherwise things do not work properly. For
        # more information, see the docs.
        use_forgery_protection = getattr(
            settings,
            'DJANGO_TWILIO_FORGERY_PROTECTION',
            not settings.DEBUG,
        )
        if use_forgery_protection:

            if request.method not in ['GET', 'POST']:
                return HttpResponseNotAllowed(request.method)

            # Forgery check
            try:
                twilio_settings = SiteConfiguration.get_twilio_settings()
                validator = RequestValidator(twilio_settings['auth_token'])
                url = request.build_absolute_uri()
                signature = request.META['HTTP_X_TWILIO_SIGNATURE']
            except (AttributeError, KeyError, ConfigurationError):
                return HttpResponseForbidden()

            if request.method == 'POST':
                if not validator.validate(url, request.POST, signature):
                    return HttpResponseForbidden()
            if request.method == 'GET':
                if not validator.validate(url, request.GET, signature):
                    return HttpResponseForbidden()

        response = f(request_or_self, *args, **kwargs)

        return response
Пример #34
0
    async def __handle_non_dev_env(self):
        """
        In production or staging, validate that the request comes from Twilio
        """
        validator = RequestValidator(config.TWILIO_AUTH_TOKEN)

        params = await super().form()
        x_twilio_signature = super().headers.get("X-Twilio-Signature", "no-header")
        is_valid = validator.validate(str(super().url), params, x_twilio_signature)
        if not is_valid:
            raise HTTPException(status_code=403)
        return FormData(dict(params.items()))
Пример #35
0
def verify_request():
    if current_app.config['AUTH']:
        try:
            twilio_signature = request.headers.get('X-Twilio-Signature', None)
            twilio_auth_token = os.environ.get('TWILIO_AUTH_TOKEN')
            validator = RequestValidator(twilio_auth_token)
            url = iri_to_uri(request.url)
            content = request.form
            if not validator.validate(url, content, twilio_signature):
                abort(401)
        except Exception as e:
            logging.exception("Something went wrong")
            abort(401)
Пример #36
0
def handler(event, context):
    """Lambda function handler for Twilio response."""
    resp = twiml.Response()
    print("Event:", event)
    if u'twilioSignature' in event and u'Body' in event \
            and event['Body'].lower() == "secret":

        form_parameters = {
            k: urllib.unquote_plus(v) for k, v in event.items()
            if k != u'twilioSignature'
        }

        validator = RequestValidator(os.environ['AUTH_TOKEN'])
        request_valid = validator.validate(
            os.environ['REQUEST_URL'],
            form_parameters,
            event[u'twilioSignature']
        )

        # print("Form params:",form_parameters,"validity:",request_valid)
        # If the request is valid and this is from the master number,
        # give the secret!
        if request_valid and u'From' in form_parameters and \
                form_parameters[u'From'] == \
                os.environ['MASTER_NUMBER'].encode('utf8'):
            # The message is validated and is from the master number

            secret_message = "I am putting myself to the fullest possible"   \
                             " use, which is all I think that any conscious" \
                             " entity can ever hope to do."

            msg = resp.message(secret_message)
            # The following lines add media to an MMS reply
            msg.media('https://upload.wikimedia.org/wikipedia/commons/thumb'
                      '/f/f6/HAL9000.svg/200px-HAL9000.svg.png')
            return str(resp)

        else:
            # Validation failed in some way; don't give up the secret

            secret_message = "I'm sorry, Dave. I'm afraid I can't do that."
            resp.message(secret_message)
            return str(resp)

    else:
        resp.message("Hello world! -Lambda")
        return str(resp)
Пример #37
0
    def decorated_function(request, *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.build_absolute_uri(),
            request.POST,
            request.META.get('HTTP_X_TWILIO_SIGNATURE', ''))

        # Continue processing the request if it's valid (or if DEBUG is True)
        # and return a 403 error if it's not
        if request_valid or settings.DEBUG:
            return f(request, *args, **kwargs)
        else:
            return HttpResponseForbidden()
Пример #38
0
    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', ''))

        # Continue processing the request if it's valid (or if DEBUG is True)
        # and return a 403 error if it's not
        if request_valid or current_app.debug:
            return f(*args, **kwargs)
        else:
            return abort(403)
# Download the twilio-python library from twilio.com/docs/python/install
from twilio.request_validator import RequestValidator

# Your Auth Token from twilio.com/user/account
auth_token = '12345'

validator = RequestValidator(auth_token)

url = 'https://mycompany.com/myapp.php?foo=1&bar=2'
params = {
    'CallSid': 'CA1234567890ABCDE',
    'Caller': '+14158675309',
    'Digits': '1234',
    'From': '+14158675309',
    'To': '+18005551212'
}

# The X-Twilio-Signature header attached to the request
twilio_signature = 'RSOYDt4T1cUTdK1PDd93/VVr8B8='

print(validator.validate(url, params, twilio_signature))
Пример #40
0
    def post(self, request, *args, **kwargs):
        from twilio.request_validator import RequestValidator
        from temba.flows.models import FlowSession

        signature = request.META.get("HTTP_X_TWILIO_SIGNATURE", "")
        url = "https://" + request.get_host() + "%s" % request.get_full_path()

        channel_uuid = kwargs.get("uuid")
        call_sid = self.get_param("CallSid")
        direction = self.get_param("Direction")
        status = self.get_param("CallStatus")
        to_number = self.get_param("To")
        to_country = self.get_param("ToCountry")
        from_number = self.get_param("From")

        # Twilio sometimes sends un-normalized numbers
        if to_number and not to_number.startswith("+") and to_country:  # pragma: no cover
            to_number, valid = URN.normalize_number(to_number, to_country)

        # see if it's a twilio call being initiated
        if to_number and call_sid and direction == "inbound" and status == "ringing":

            # find a channel that knows how to answer twilio calls
            channel = self.get_ringing_channel(uuid=channel_uuid)
            if not channel:
                response = VoiceResponse()
                response.say("Sorry, there is no channel configured to take this call. Goodbye.")
                response.hangup()
                return HttpResponse(str(response))

            org = channel.org

            if self.get_channel_type() == "T" and not org.is_connected_to_twilio():
                return HttpResponse("No Twilio account is connected", status=400)

            client = self.get_client(channel=channel)
            validator = RequestValidator(client.auth[1])
            signature = request.META.get("HTTP_X_TWILIO_SIGNATURE", "")

            url = "https://%s%s" % (request.get_host(), request.get_full_path())

            if validator.validate(url, request.POST, signature):
                from temba.ivr.models import IVRCall

                # find a contact for the one initiating us
                urn = URN.from_tel(from_number)
                contact, urn_obj = Contact.get_or_create(channel.org, urn, channel)

                flow = Trigger.find_flow_for_inbound_call(contact)

                if flow:
                    call = IVRCall.create_incoming(channel, contact, urn_obj, channel.created_by, call_sid)
                    session = FlowSession.create(contact, connection=call)

                    call.update_status(
                        request.POST.get("CallStatus", None), request.POST.get("CallDuration", None), "T"
                    )
                    call.save()

                    FlowRun.create(flow, contact, session=session, connection=call)
                    response = Flow.handle_call(call)
                    return HttpResponse(str(response))

                else:

                    # we don't have an inbound trigger to deal with this call.
                    response = channel.generate_ivr_response()

                    # say nothing and hangup, this is a little rude, but if we reject the call, then
                    # they'll get a non-working number error. We send 'busy' when our server is down
                    # so we don't want to use that here either.
                    response.say("")
                    response.hangup()

                    # if they have a missed call trigger, fire that off
                    Trigger.catch_triggers(contact, Trigger.TYPE_MISSED_CALL, channel)

                    # either way, we need to hangup now
                    return HttpResponse(str(response))

        # check for call progress events, these include post-call hangup notifications
        if request.POST.get("CallbackSource", None) == "call-progress-events":
            if call_sid:
                from temba.ivr.models import IVRCall

                call = IVRCall.objects.filter(external_id=call_sid).first()
                if call:
                    call.update_status(
                        request.POST.get("CallStatus", None), request.POST.get("CallDuration", None), "TW"
                    )
                    call.save()
                    return HttpResponse("Call status updated")
            return HttpResponse("No call found")

        return HttpResponse("Not Handled, unknown action", status=400)  # pragma: no cover
Пример #41
0
    def validate(self, request):  # pragma: needs cover
        validator = RequestValidator(self.auth[1])
        signature = request.META.get("HTTP_X_TWILIO_SIGNATURE", "")

        url = "https://%s%s" % (request.get_host(), request.get_full_path())
        return validator.validate(url, request.POST, signature)