Ejemplo n.º 1
0
    def validate(self, uri, params, signature):
        """Compute the signature for a given request

        :param uri: full URI that Twilio requested on your server
        :param params: post vars that Twilio sent with the request
        :param utf: whether return should be bytestring or unicode (python3)

        :returns: Boolean indicating if the signature was valid or not
        """
        if params is None:
            params = {}

        parsed_uri = urlparse(uri)
        uri_with_port = add_port(parsed_uri)
        uri_without_port = remove_port(parsed_uri)

        signature_bytes = base64.b64decode(signature)

        # compute signature with Ed25519 algorithm
        #  check signature of uri with and without port,
        #  since sig generation on back end is inconsistent
        for uri in [uri_without_port, uri_with_port]:
            try:
                self._verify_key.verify(self._compute_signed_bytes(
                    uri, params),
                                        signature=signature_bytes)
            except BadSignatureError:
                continue
            else:
                return True

        return False
    def validate(self, uri, params, signature):
        """Validate a request from Twilio

        :param uri: full URI that Twilio requested on your server
        :param params: dictionary of POST variables or string of POST body for JSON requests
        :param signature: expected signature in HTTP X-Twilio-Signature header

        :returns: True if the request passes validation, False if not
        """
        if params is None:
            params = {}

        parsed_uri = urlparse(uri)
        if parsed_uri.scheme == "https" and parsed_uri.port:
            uri = remove_port(parsed_uri)

        valid_signature = False  # Default fail
        valid_body_hash = True  # May not receive body hash, so default succeed

        query = parse_qs(parsed_uri.query)
        if "bodySHA256" in query and isinstance(params, string_types):
            valid_body_hash = compare(self.compute_hash(params),
                                      query["bodySHA256"][0])
            valid_signature = compare(self.compute_signature(uri, {}),
                                      signature)
        else:
            valid_signature = compare(self.compute_signature(uri, params),
                                      signature)

        return valid_signature and valid_body_hash
Ejemplo n.º 3
0
    def validate(self, uri, params, signature):
        """Validate a request from Twilio

        :param uri: full URI that Twilio requested on your server
        :param params: dictionary of POST variables or string of POST body for JSON requests
        :param signature: expected signature in HTTP X-Twilio-Signature header

        :returns: True if the request passes validation, False if not
        """
        if params is None:
            params = {}

        parsed_uri = urlparse(uri)
        if parsed_uri.scheme == "https" and parsed_uri.port:
            uri = remove_port(parsed_uri)

        valid_signature = False  # Default fail
        valid_body_hash = True  # May not receive body hash, so default succeed

        query = parse_qs(parsed_uri.query)
        if "bodySHA256" in query and isinstance(params, string_types):
            valid_body_hash = compare(self.compute_hash(params), query["bodySHA256"][0])
            valid_signature = compare(self.compute_signature(uri, {}), signature)
        else:
            valid_signature = compare(self.compute_signature(uri, params), signature)

        return valid_signature and valid_body_hash
    def validate(self, uri, params, signature):
        """Validate a request from Twilio

        :param uri: full URI that Twilio requested on your server
        :param params: dictionary of POST variables or string of POST body for JSON requests
        :param signature: expected signature in HTTP X-Twilio-Signature header

        :returns: True if the request passes validation, False if not
        """
        if params is None:
            params = {}

        parsed_uri = urlparse(uri)
        uri_with_port = add_port(parsed_uri)
        uri_without_port = remove_port(parsed_uri)

        valid_signature = False  # Default fail
        valid_signature_with_port = False
        valid_body_hash = True  # May not receive body hash, so default succeed

        query = parse_qs(parsed_uri.query)
        if "bodySHA256" in query and isinstance(params, string_types):
            valid_body_hash = compare(self.compute_hash(params),
                                      query["bodySHA256"][0])
            params = {}

        #  check signature of uri with and without port,
        #  since sig generation on back end is inconsistent
        valid_signature = compare(
            self.compute_signature(uri_without_port, params), signature)
        valid_signature_with_port = compare(
            self.compute_signature(uri_with_port, params), signature)

        return valid_body_hash and (valid_signature
                                    or valid_signature_with_port)
Ejemplo n.º 5
0
    def iter(self, **kwargs):
        """ Return all instance resources using an iterator

        This will fetch a page of resources from the API and yield them in
        turn. When the page is exhausted, this will make a request to the API
        to retrieve the next page. Hence you may notice a pattern - the library
        will loop through 50 objects very quickly, but there will be a delay
        retrieving the 51st as the library must make another request to the API
        for resources.

        Example usage:

        .. code-block:: python

            for message in client.messages:
                print message.sid
        """
        params = transform_params(kwargs)

        while True:
            resp, page = self.request("GET", self.uri, params=params)

            if self.key not in page:
                raise StopIteration()

            for ir in page[self.key]:
                yield self.load_instance(ir)

            if not page.get('next_page_uri', ''):
                raise StopIteration()

            o = urlparse(page['next_page_uri'])
            params.update(parse_qs(o.query))
Ejemplo n.º 6
0
    def iter(self, **kwargs):
        """ Return all instance resources using an iterator

        This will fetch a page of resources from the API and yield them in
        turn. When the page is exhausted, this will make a request to the API
        to retrieve the next page. Hence you may notice a pattern - the library
        will loop through 50 objects very quickly, but there will be a delay
        retrieving the 51st as the library must make another request to the API
        for resources.

        Example usage:

        .. code-block:: python

            for message in client.messages:
                print message.sid
        """
        params = transform_params(kwargs)

        while True:
            resp, page = self.request("GET", self.uri, params=params)

            if self.key not in page:
                raise StopIteration()

            for ir in page[self.key]:
                yield self.load_instance(ir)

            if not page.get('next_page_uri', ''):
                raise StopIteration()

            o = urlparse(page['next_page_uri'])
            params.update(parse_qs(o.query))
Ejemplo n.º 7
0
    def get_hostname(self, uri):
        """
        Determines the proper hostname given edge and region preferences
        via client configuration or uri.

        :param str uri: Fully qualified url

        :returns: The final uri used to make the request
        :rtype: str
        """
        if not self.edge and not self.region:
            return uri

        parsed_url = urlparse(uri)
        pieces = parsed_url.netloc.split('.')
        prefix = pieces[0]
        suffix = '.'.join(pieces[-2:])
        region = None
        edge = None
        if len(pieces) == 4:
            # product.region.twilio.com
            region = pieces[1]
        elif len(pieces) == 5:
            # product.edge.region.twilio.com
            edge = pieces[1]
            region = pieces[2]

        edge = self.edge or edge
        region = self.region or region or (edge and 'us1')

        parsed_url = parsed_url._replace(
            netloc='.'.join([part for part in [prefix, edge, region, suffix] if part])
        )
        return urlunparse(parsed_url)
    def request(self,
                method,
                url,
                params=None,
                data=None,
                headers=None,
                auth=None,
                timeout=None,
                allow_redirects=False):
        """Sends an HTTP request

        :param str method: The HTTP method to use
        :param str url: The URL to request
        :param dict params: Query parameters to append to the URL
        :param dict data: Parameters to go in the body of the HTTP request
        :param dict headers: HTTP Headers to send with the request
        :param tuple auth: Basic Auth arguments
        :param float timeout: Socket/Read timeout for the request
        :param boolean allow_redirects: Whether or not to allow redirects

        :return: An http response
        :rtype: A :class:`Response <twilio.rest.http.response.Response>` object

        See the requests documentation for explanation of all these parameters
        """
        http = httplib2.Http(
            timeout=timeout,
            ca_certs=get_cert_file(),
            proxy_info=self.proxy_info,
        )
        http.follow_redirects = allow_redirects

        if auth is not None:
            http.add_credentials(auth[0], auth[1])

        if data is not None:
            udata = {}
            for k, v in iteritems(data):
                key = k.encode('utf-8')
                if isinstance(v, (list, tuple, set)):
                    udata[key] = [self.encode_atom(x) for x in v]
                elif isinstance(v, (integer_types, binary_type, string_types)):
                    udata[key] = self.encode_atom(v)
                else:
                    raise ValueError('data should be an integer, '
                                     'binary, or string, or sequence ')
            data = urlencode(udata, doseq=True)

        if params is not None:
            enc_params = urlencode(params, doseq=True)
            if urlparse(url).query:
                url = '%s&%s' % (url, enc_params)
            else:
                url = '%s?%s' % (url, enc_params)

        resp, content = http.request(url, method, headers=headers, body=data)

        return Response(int(resp.status), content.decode('utf-8'))
Ejemplo n.º 9
0
    def validate(self, uri, params, signature):
        """Validate a request from Twilio

        :param uri: full URI that Twilio requested on your server
        :param params: post vars that Twilio sent with the request
        :param signature: expected signature in HTTP X-Twilio-Signature header

        :returns: True if the request passes validation, False if not
        """
        parsed_uri = urlparse(uri)
        if parsed_uri.scheme == "https" and parsed_uri.port:
            uri = remove_port(parsed_uri)
        return compare(self.compute_signature(uri, params), signature)
Ejemplo n.º 10
0
    def validate(self, uri, params, signature):
        """Validate a request from Twilio

        :param uri: full URI that Twilio requested on your server
        :param params: post vars that Twilio sent with the request
        :param signature: expected signature in HTTP X-Twilio-Signature header

        :returns: True if the request passes validation, False if not
        """
        parsed_uri = urlparse(uri)
        # https://www.twilio.com/docs/api/security#notes says that HTTPS port should be ommited
        # but if https port isn't default - validation webhook fails
        # related issue https://github.com/twilio/twilio-python/issues/402
        if parsed_uri.scheme == "https" and parsed_uri.port == 443:
            uri = remove_port(parsed_uri)
        return compare(self.compute_signature(uri, params), signature)
Ejemplo n.º 11
0
def make_request(method,
                 url,
                 params=None,
                 data=None,
                 headers=None,
                 cookies=None,
                 files=None,
                 auth=None,
                 timeout=None,
                 allow_redirects=False,
                 proxies=None):
    """Sends an HTTP request Returns :class:`Response <models.Response>`

    See the requests documentation for explanation of all these parameters

    Currently proxies, files, and cookies are all ignored
    """
    http = httplib2.Http(timeout=timeout, ca_certs=get_cert_file())
    http.follow_redirects = allow_redirects

    if auth is not None:
        http.add_credentials(auth[0], auth[1])

    if data is not None:
        udata = {}
        for k, v in iteritems(data):
            key = k.encode('utf-8')
            if isinstance(v, (integer_types, binary_type)):
                udata[key] = v
            elif isinstance(v, string_types):
                udata[key] = v.encode('utf-8')
            else:
                raise ValueError('data should be an integer, '
                                 'binary, or string')
        data = urlencode(udata)

    if params is not None:
        enc_params = urlencode(params, doseq=True)
        if urlparse(url).query:
            url = '%s&%s' % (url, enc_params)
        else:
            url = '%s?%s' % (url, enc_params)

    resp, content = http.request(url, method, headers=headers, body=data)

    # Format httplib2 request as requests object
    return Response(resp, content.decode('utf-8'), url)
Ejemplo n.º 12
0
    def _build_validation_payload(self, request):
        """
        Extract relevant information from request to build a ClientValidationJWT
        :param PreparedRequest request: request we will extract information from.
        :return: ValidationPayload
        """
        parsed = urlparse(request.url)
        path = parsed.path
        query_string = parsed.query or ''

        return ValidationPayload(
            method=request.method,
            path=path,
            query_string=query_string,
            all_headers=request.headers,
            signed_headers=ValidationClient.__SIGNED_HEADERS,
            body=request.body or '')
Ejemplo n.º 13
0
    def _build_validation_payload(self, request):
        """
        Extract relevant information from request to build a ClientValidationJWT
        :param PreparedRequest request: request we will extract information from.
        :return: ValidationPayload
        """
        parsed = urlparse(request.url)
        path = parsed.path
        query_string = parsed.query or ''

        return ValidationPayload(
            method=request.method,
            path=path,
            query_string=query_string,
            all_headers=request.headers,
            signed_headers=ValidationClient.__SIGNED_HEADERS,
            body=request.body or ''
        )
Ejemplo n.º 14
0
    def iter(self, **kwargs):
        """
        Return all instance resources using an iterator
        """
        params = transform_params(kwargs)

        while True:
            resp, page = self.request("GET", self.uri, params=params)

            if self.key not in page:
                raise StopIteration()

            for ir in page[self.key]:
                yield self.load_instance(ir)

            if not page.get('next_page_uri', ''):
                raise StopIteration()

            o = urlparse(page['next_page_uri'])
            params.update(parse_qs(o.query))
Ejemplo n.º 15
0
    def iter(self, **kwargs):
        """
        Return all instance resources using an iterator
        """
        params = transform_params(kwargs)

        while True:
            resp, page = self.request("GET", self.uri, params=params)

            if self.key not in page:
                raise StopIteration()

            for ir in page[self.key]:
                yield self.load_instance(ir)

            if not page.get('next_page_uri', ''):
                raise StopIteration()

            o = urlparse(page['next_page_uri'])
            params.update(parse_qs(o.query))
Ejemplo n.º 16
0
def make_request(method, url, params=None, data=None, headers=None,
                 cookies=None, files=None, auth=None, timeout=None,
                 allow_redirects=False, proxies=None):
    """Sends an HTTP request Returns :class:`Response <models.Response>`

    See the requests documentation for explanation of all these parameters

    Currently proxies, files, and cookies are all ignored
    """
    http = httplib2.Http(timeout=timeout)
    http.follow_redirects = allow_redirects

    if auth is not None:
        http.add_credentials(auth[0], auth[1])

    if data is not None:
        udata = {}
        for k, v in iteritems(data):
            key = k.encode('utf-8')
            if isinstance(v, (integer_types, binary_type)):
                udata[key] = v
            elif isinstance(v, string_types):
                udata[key] = v.encode('utf-8')
            else:
                raise ValueError('data should be an integer, '
                                 'binary, or string')
        data = urlencode(udata)

    if params is not None:
        enc_params = urlencode(params, doseq=True)
        if urlparse(url).query:
            url = '%s&%s' % (url, enc_params)
        else:
            url = '%s?%s' % (url, enc_params)

    resp, content = http.request(url, method, headers=headers, body=data)

    # Format httplib2 request as requests object
    return Response(resp, content.decode('utf-8'), url)
Ejemplo n.º 17
0
def make_request(method, url, params=None, data=None, headers=None,
                 cookies=None, files=None, auth=None, timeout=None,
                 allow_redirects=False, proxies=None):
    """Sends an HTTP request

    :param str method: The HTTP method to use
    :param str url: The URL to request
    :param dict params: Query parameters to append to the URL
    :param dict data: Parameters to go in the body of the HTTP request
    :param dict headers: HTTP Headers to send with the request
    :param float timeout: Socket/Read timeout for the request

    :return: An http response
    :rtype: A :class:`Response <models.Response>` object

    See the requests documentation for explanation of all these parameters

    Currently proxies, files, and cookies are all ignored
    """
    http = httplib2.Http(
        timeout=timeout,
        ca_certs=get_cert_file(),
        proxy_info=Connection.proxy_info(),
    )
    http.follow_redirects = allow_redirects

    if auth is not None:
        http.add_credentials(auth[0], auth[1])

    def encode_atom(atom):
            if isinstance(atom, (integer_types, binary_type)):
                return atom
            elif isinstance(atom, string_types):
                return atom.encode('utf-8')
            else:
                raise ValueError('list elements should be an integer, '
                                 'binary, or string')

    if data is not None:
        udata = {}
        for k, v in iteritems(data):
            key = k.encode('utf-8')
            if isinstance(v, (list, tuple, set)):
                udata[key] = [encode_atom(x) for x in v]
            elif isinstance(v, (integer_types, binary_type, string_types)):
                udata[key] = encode_atom(v)
            else:
                raise ValueError('data should be an integer, '
                                 'binary, or string, or sequence ')
        data = urlencode(udata, doseq=True)

    if params is not None:
        enc_params = urlencode(params, doseq=True)
        if urlparse(url).query:
            url = '%s&%s' % (url, enc_params)
        else:
            url = '%s?%s' % (url, enc_params)

    resp, content = http.request(url, method, headers=headers, body=data)

    # Format httplib2 request as requests object
    return Response(resp, content.decode('utf-8'), url)
Ejemplo n.º 18
0
def make_request(method,
                 url,
                 params=None,
                 data=None,
                 headers=None,
                 cookies=None,
                 files=None,
                 auth=None,
                 timeout=None,
                 allow_redirects=False,
                 proxies=None):
    """Sends an HTTP request

    :param str method: The HTTP method to use
    :param str url: The URL to request
    :param dict params: Query parameters to append to the URL
    :param dict data: Parameters to go in the body of the HTTP request
    :param dict headers: HTTP Headers to send with the request
    :param float timeout: Socket/Read timeout for the request

    :return: An http response
    :rtype: A :class:`Response <models.Response>` object

    See the requests documentation for explanation of all these parameters

    Currently proxies, files, and cookies are all ignored
    """
    http = httplib2.Http(
        timeout=timeout,
        ca_certs=get_cert_file(),
        proxy_info=Connection.proxy_info(),
    )
    http.follow_redirects = allow_redirects

    if auth is not None:
        http.add_credentials(auth[0], auth[1])

    def encode_atom(atom):
        if isinstance(atom, (integer_types, binary_type)):
            return atom
        elif isinstance(atom, string_types):
            return atom.encode('utf-8')
        else:
            raise ValueError('list elements should be an integer, '
                             'binary, or string')

    if data is not None:
        udata = {}
        for k, v in iteritems(data):
            key = k.encode('utf-8')
            if isinstance(v, (list, tuple, set)):
                udata[key] = [encode_atom(x) for x in v]
            elif isinstance(v, (integer_types, binary_type, string_types)):
                udata[key] = encode_atom(v)
            else:
                raise ValueError('data should be an integer, '
                                 'binary, or string, or sequence ')
        data = urlencode(udata, doseq=True)

    if params is not None:
        enc_params = urlencode(params, doseq=True)
        if urlparse(url).query:
            url = '%s&%s' % (url, enc_params)
        else:
            url = '%s?%s' % (url, enc_params)

    resp, content = http.request(url, method, headers=headers, body=data)

    # Format httplib2 request as requests object
    return Response(resp, content.decode('utf-8'), url)
Ejemplo n.º 19
0
 def _get_host(self, request):
     """Pull the Host out of the request"""
     parsed = urlparse(request.url)
     return parsed.netloc
Ejemplo n.º 20
0
 def _get_host(self, request):
     """Pull the Host out of the request"""
     parsed = urlparse(request.url)
     return parsed.netloc