def _build_request(self, method, request_uri, body=u"", headers={}):
        # oauthlib expects None instead of empty string
        method = unicode(method)
        request_uri = unicode(request_uri)
        extracted_body = extract_params(body)
        if extracted_body:
            # contenttype sometimes is ...form-data; boundary=X
            contenttype = headers.get('Content-Type', '').split(';', 1)[0]
            if contenttype == CONTENT_TYPE_FORM:
                uri, headers, body = self.client.sign(
                    uri=request_uri,
                    http_method=method,
                    body=extracted_body,
                    headers=headers)
            elif contenttype == CONTENT_TYPE_MULTI:
                uri, headers, _discard = self.client.sign(
                    uri=request_uri,
                    http_method=method,
                    body=None,
                    headers=headers)
        else:
            uri, headers, _discard = self.client.sign(
                uri=request_uri,
                http_method=method,
                body=None,
                headers=headers)

        return super(OAUTH1HTTPClient, self)._build_request(
            method, uri, body=body, headers=headers)
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.

        content_type = r.headers.get('Content-Type', '')
        if (not content_type and extract_params(r.body)
                or self.client.signature_type == SIGNATURE_TYPE_BODY):
            content_type = CONTENT_TYPE_FORM_URLENCODED
        if not isinstance(content_type, unicode):
            content_type = content_type.decode('utf-8')

        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)

        if is_form_encoded:
            r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            r.url, headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)
        elif self.force_include_body:
            # To allow custom clients to work on non form encoded bodies.
            r.url, headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)
        else:
            # Omit body data in the signing of non form-encoded requests
            r.url, headers, _ = self.client.sign(
                unicode(r.url), unicode(r.method), None, r.headers)

        r.prepare_headers(headers)
        r.url = to_native_string(r.url)
        return r
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.

        content_type = r.headers.get('Content-Type', '')
        if not content_type and extract_params(r.body):
            content_type = CONTENT_TYPE_FORM_URLENCODED
        if not isinstance(content_type, unicode):
            content_type = content_type.decode('utf-8')

        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)

        if is_form_encoded:
            r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            r.url, headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)
        else:
            r.url, headers, _ = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)

        r.prepare_headers(headers)
        r.url = to_native_str(r.url)
        return r
Beispiel #4
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.

        content_type = r.headers.get('Content-Type'.encode('utf-8'), '')
        if not isinstance(content_type, unicode):
            content_type = content_type.decode('utf-8')

        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)

        if is_form_encoded or extract_params(r.body):
            r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            r.url, r.headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)
        else:
            # Omit body data in the signing of non form-encoded requests
            r.url, r.headers, _ = self.client.sign(
                unicode(r.url), unicode(r.method), None, r.headers)

        return r
Beispiel #5
0
    def sign(self, url, method, body, headers):
        """Returns the url, headers and body inc. the oauth1 stuff

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        content_type = headers.get('Content-Type', '')
        if (not content_type and extract_params(body)
                or self.client.signature_type == SIGNATURE_TYPE_BODY):
            content_type = CONTENT_TYPE_FORM_URLENCODED

        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)

        log.debug('Including body in call to sign: %s', is_form_encoded
                  or self.force_include_body)

        if is_form_encoded:
            headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            url, headers, body = self.client.sign(url, method, body or '',
                                                  headers)
        elif self.force_include_body:
            # To allow custom clients to work on non form encoded bodies.
            url, headers, body = self.client.sign(url, method, body or '',
                                                  headers)
        else:
            # Omit body data in the signing of non form-encoded requests
            url, headers, _ = self.client.sign(url, method, None, headers)

        return url, body, headers
Beispiel #6
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.

        content_type = r.headers.get("Content-Type".encode("utf-8"), "")
        if not isinstance(content_type, unicode):
            content_type = content_type.decode("utf-8")

        is_form_encoded = CONTENT_TYPE_FORM_URLENCODED in content_type

        if is_form_encoded or extract_params(r.body):
            r.headers["Content-Type"] = CONTENT_TYPE_FORM_URLENCODED
            r.url, r.headers, r.body = self.client.sign(unicode(r.url), unicode(r.method), r.body or "", r.headers)
        else:
            # Omit body data in the signing of non form-encoded requests
            r.url, r.headers, _ = self.client.sign(unicode(r.url), unicode(r.method), None, r.headers)

        r.url = to_native_str(r.url)

        return r
Beispiel #7
0
    def __call__(self, r):
        contenttype = r.headers.get('Content-Type', None)
        decoded_body = extract_params(r.data)
        if contenttype == None and decoded_body != None:
            r.headers['Content-Type'] = 'application/x-www-form-urlencoded'

        r.url, r.headers, r.data = self.client.sign(
            unicode(r.url), unicode(r.method), r.data, r.headers)
        return r
Beispiel #8
0
    def __call__(self, r):
        contenttype = r.headers.get('Content-Type', None)
        decoded_body = extract_params(r.data)
        if contenttype == None and decoded_body != None:
            r.headers['Content-Type'] = 'application/x-www-form-urlencoded'

        r.url, r.headers, r.data = self.client.sign(unicode(r.url),
                                                    unicode(r.method), r.data,
                                                    r.headers)
        return r
Beispiel #9
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set an educated guess is made.
        """
        # split(";") because Content-Type may be "multipart/form-data; boundary=xxxxx"
        contenttype = r.headers.get('Content-Type', '').split(";")[0].lower()
        # extract_params will not give params unless the body is a properly
        # formatted string, a dictionary or a list of 2-tuples.
        decoded_body = extract_params(r.body)

        # extract_params can only check the present r.data and does not know
        # of r.files, thus an extra check is performed. We know that
        # if files are present the request will not have
        # Content-type: x-www-form-urlencoded. We guess it will have
        # a mimetype of multipart/form-data and if this is not the case
        # we assume the correct header will be set later.
        _oauth_signed = True
        if hasattr(r, 'files') and contenttype == CONTENT_TYPE_MULTI_PART:
            # Omit body data in the signing and since it will always
            # be empty (cant add paras to body if multipart) and we wish
            # to preserve body.
            r.url, r.headers, _ = self.client.sign(
                unicode(r.full_url), unicode(r.method), None, r.headers)
        elif decoded_body is not None and contenttype in (CONTENT_TYPE_FORM_URLENCODED, ''):
            # Normal signing
            if not contenttype:
                r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            r.url, r.headers, r.data = self.client.sign(
                unicode(r.full_url), unicode(r.method), r.data, r.headers)
        else:
            _oauth_signed = False
        if _oauth_signed:
            # Both flows add params to the URL by using r.full_url,
            # so this prevents adding it again later
            r.params = {}

            # Having the authorization header, key or value, in unicode will
            # result in UnicodeDecodeErrors when the request is concatenated
            # by httplib. This can easily be seen when attaching files.
            # Note that simply encoding the value is not enough since Python
            # saves the type of first key set. Thus we remove and re-add.
            # >>> d = {u'a':u'foo'}
            # >>> d['a'] = 'foo'
            # >>> d
            # { u'a' : 'foo' }
            u_header = unicode('Authorization')
            if u_header in r.headers:
                auth_header = r.headers[u_header].encode('utf-8')
                del r.headers[u_header]
                r.headers['Authorization'] = auth_header

        return r
def prepare_request_uri_query(oauth_params, uri):
    """Prepare the Request URI Query.

    Per `section 3.5.3`_ of the spec.

    .. _`section 3.5.3`: http://tools.ietf.org/html/rfc5849#section-3.5.3

    """
    # append OAuth params to the existing set of query components
    sch, net, path, par, query, fra = urlparse(uri)
    query = urlencode(_append_params(oauth_params, extract_params(query) or []))
    return urlunparse((sch, net, path, par, query, fra))
Beispiel #11
0
def prepare_request_uri_query(oauth_params, uri):
    """Prepare the Request URI Query.

    Per `section 3.5.3`_ of the spec.

    .. _`section 3.5.3`: http://tools.ietf.org/html/rfc5849#section-3.5.3

    """
    # append OAuth params to the existing set of query components
    sch, net, path, par, query, fra = urlparse(uri)
    query = urlencode(_append_params(oauth_params, extract_params(query) or []))
    return urlunparse((sch, net, path, par, query, fra))
Beispiel #12
0
    async def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.
        log.debug("Signing request %s using client %s", r, self.client)
        r.raw_body = await r.body()
        content_type = r.headers.get("Content-Type", "")
        if (
            not content_type
            and extract_params(r.raw_body)
            or self.client.signature_type == SIGNATURE_TYPE_BODY
        ):
            content_type = CONTENT_TYPE_FORM_URLENCODED
        if not isinstance(content_type, unicode):
            content_type = content_type.decode("utf-8")

        is_form_encoded = CONTENT_TYPE_FORM_URLENCODED in content_type

        log.debug(
            "Including body in call to sign: %s",
            is_form_encoded or self.force_include_body,
        )

        if is_form_encoded:
            r.headers["Content-Type"] = CONTENT_TYPE_FORM_URLENCODED
            r.url, headers, r.raw_body = self.client.sign(
                unicode(r.url), unicode(r.method), r.raw_body or "", r.headers
            )
        elif self.force_include_body:
            # To allow custom clients to work on non form encoded bodies.
            r.url, headers, r.raw_body = self.client.sign(
                unicode(r.url), unicode(r.method), r.raw_body or "", r.headers
            )
        else:
            # Omit body data in the signing of non form-encoded requests
            # noinspection PyArgumentEqualDefault
            r.url, headers, _ = self.client.sign(
                unicode(r.url), unicode(r.method), None, r.headers
            )

        r.prepare_headers(headers)
        r.url = to_native_string(r.url)
        log.debug("Updated url: %s", r.url)
        log.debug("Updated headers: %s", headers)
        log.debug("Updated body: %r", r.raw_body)
        return r
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.
        log.debug("Signing request %s using client %s", r, self.client)

        content_type = r.headers.get("Content-Type", "")
        if (
            not content_type
            and extract_params(r.body)
            or self.client.signature_type == SIGNATURE_TYPE_BODY
        ):
            content_type = CONTENT_TYPE_FORM_URLENCODED
        if not isinstance(content_type, unicode):
            content_type = content_type.decode("utf-8")

        is_form_encoded = CONTENT_TYPE_FORM_URLENCODED in content_type

        log.debug(
            "Including body in call to sign: %s",
            is_form_encoded or self.force_include_body,
        )

        if is_form_encoded:
            r.headers["Content-Type"] = CONTENT_TYPE_FORM_URLENCODED
            r.url, headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or "", r.headers
            )
        elif self.force_include_body:
            # To allow custom clients to work on non form encoded bodies.
            r.url, headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or "", r.headers
            )
        else:
            # Omit body data in the signing of non form-encoded requests
            r.url, headers, _ = self.client.sign(
                unicode(r.url), unicode(r.method), None, r.headers
            )

        r.prepare_headers(headers)
        r.url = to_native_string(r.url)
        log.debug("Updated url: %s", r.url)
        log.debug("Updated headers: %s", headers)
        log.debug("Updated body: %r", r.body)
        return r
Beispiel #14
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set an educated guess is made.
        """
        contenttype = r.headers.get('Content-Type', None)
        # extract_params will not give params unless the body is a properly
        # formatted string, a dictionary or a list of 2-tuples.
        decoded_body = extract_params(r.data)
        if contenttype == None and decoded_body != None:
            # extract_params can only check the present r.data and does not know
            # of r.files, thus an extra check is performed. We know that
            # if files are present the request will not have
            # Content-type: x-www-form-urlencoded. We guess it will have
            # a mimetype of multipart/form-encoded and if this is not the case
            # we assume the correct header will be set later.
            if r.files:
                # Omit body data in the signing and since it will always
                # be empty (cant add paras to body if multipart) and we wish
                # to preserve body.
                r.headers['Content-Type'] = 'multipart/form-encoded'
                r.url, r.headers, _ = self.client.sign(unicode(r.url),
                                                       unicode(r.method), None,
                                                       r.headers)
            else:
                # Normal signing
                r.headers['Content-Type'] = 'application/x-www-form-urlencoded'
                r.url, r.headers, r.data = self.client.sign(
                    unicode(r.url), unicode(r.method), r.data, r.headers)

            # Having the authorization header, key or value, in unicode will
            # result in UnicodeDecodeErrors when the request is concatenated
            # by httplib. This can easily be seen when attaching files.
            # Note that simply encoding the value is not enough since Python
            # saves the type of first key set. Thus we remove and re-add.
            # >>> d = {u'a':u'foo'}
            # >>> d['a'] = 'foo'
            # >>> d
            # { u'a' : 'foo' }
            u_header = unicode('Authorization')
            if u_header in r.headers:
                auth_header = r.headers[u_header].encode('utf-8')
                del r.headers[u_header]
                r.headers['Authorization'] = auth_header

            return r
Beispiel #15
0
    def test_request_request_token_with_valid_credentials(self):
        headers = {'wsgi.url_scheme': 'https', 'Authorization': 'oauth_consumer_key="%s", oauth_consumer_secret="%s", oauth_signature_method="PLAINTEXT", oauth_signature="%s&", oauth_timestamp="%d", oauth_nonce="%s", oauth_callback="oob"' % (
                self.oauth_client_key,
                self.oauth_client_secret,
                self.oauth_client_secret,
                time.mktime(datetime.datetime.now().timetuple()),
                'peanutbutterjellytime'
        )}
        response = self.client.post('/request-request-token/', **headers)

        new_token = Token.objects.filter(type=Token.REQUEST_TOKEN).latest('pk')
        response_content_params = dict(extract_params(to_unicode(response.content, 'utf-8')))

        self.assertEqual(200, response.status_code)
        self.assertEqual('application/x-www-form-urlencoded', response['Content-Type'])
        self.assertEqual(new_token.key, response_content_params['oauth_token'])
        self.assertEqual(new_token.secret, response_content_params['oauth_token_secret'])
Beispiel #16
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set an educated guess is made.
        """
        contenttype = r.headers.get('Content-Type', None)
        # extract_params will not give params unless the body is a properly
        # formatted string, a dictionary or a list of 2-tuples.
        decoded_body = extract_params(r.data)     
        if contenttype == None and decoded_body != None:
            # extract_params can only check the present r.data and does not know
            # of r.files, thus an extra check is performed. We know that 
            # if files are present the request will not have 
            # Content-type: x-www-form-urlencoded. We guess it will have
            # a mimetype of multipart/form-encoded and if this is not the case
            # we assume the correct header will be set later.
            if r.files:
                # Omit body data in the signing and since it will always
                # be empty (cant add paras to body if multipart) and we wish
                # to preserve body. 
                r.headers['Content-Type'] = 'multipart/form-encoded'
                r.url, r.headers, _ = self.client.sign(
                    unicode(r.url), unicode(r.method), None, r.headers)
            else:
                # Normal signing
                r.headers['Content-Type'] = 'application/x-www-form-urlencoded'
                r.url, r.headers, r.data = self.client.sign(
                    unicode(r.url), unicode(r.method), r.data, r.headers)

            # Having the authorization header, key or value, in unicode will
            # result in UnicodeDecodeErrors when the request is concatenated
            # by httplib. This can easily be seen when attaching files.
            # Note that simply encoding the value is not enough since Python
            # saves the type of first key set. Thus we remove and re-add.
            # >>> d = {u'a':u'foo'}
            # >>> d['a'] = 'foo'
            # >>> d
            # { u'a' : 'foo' }
            u_header = unicode('Authorization')
            if u_header in r.headers:               
                auth_header = r.headers[u_header].encode('utf-8')
                del r.headers[u_header]
                r.headers['Authorization'] = auth_header

            return r
Beispiel #17
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.
        is_form_encoded = CONTENT_TYPE_FORM_URLENCODED in r.headers.get("Content-Type", "")

        if is_form_encoded or extract_params(r.body):
            r.headers["Content-Type"] = CONTENT_TYPE_FORM_URLENCODED
            r.url, r.headers, r.body = self.client.sign(unicode(r.url), unicode(r.method), r.body or "", r.headers)
        else:
            # Omit body data in the signing of non form-encoded requests
            r.url, r.headers, _ = self.client.sign(unicode(r.url), unicode(r.method), None, r.headers)

        # PHB HACK FIX: FORCE URL TO STR - Should be encoded already
        if type(r.url) == unicode:
            r.url = str(r.url)

        # Having the authorization header, key or value, in unicode will
        # result in UnicodeDecodeErrors when the request is concatenated
        # by httplib. This can easily be seen when attaching files.
        # Note that simply encoding the value is not enough since Python
        # saves the type of first key set. Thus we remove and re-add.
        # >>> d = {u'a':u'foo'}
        # >>> d['a'] = 'foo'
        # >>> d
        # { u'a' : 'foo' }
        u_header = unicode("Authorization")
        if u_header in r.headers:
            auth_header = r.headers[u_header].encode("utf-8")
            del r.headers[u_header]
            r.headers["Authorization"] = auth_header

        # PHB HACK FIX: FORCE HEADERS TO STR - Should be encoded already
        new_headers = {}
        for (k, v) in r.headers.iteritems():
            new_headers[str(k)] = str(v)

        r.headers = new_headers

        return r
Beispiel #18
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.
        log.debug('Signing request %s using client %s', r, self.client)

        content_type = r.headers.get('Content-Type', '')
        if (not content_type and extract_params(r.body)
                or self.client.signature_type == SIGNATURE_TYPE_BODY):
            content_type = CONTENT_TYPE_FORM_URLENCODED
        if not isinstance(content_type, unicode):
            content_type = content_type.decode('utf-8')

        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)

        if is_form_encoded:
            r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED

        if (self.force_include_body or
                            (not self.force_exclude_body and is_form_encoded)):
            log.debug('Including body in call to sign')
            r.url, headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)
        else:
            log.debug('Excluding body from call to sign')
            r_headers = r.headers.copy()
            if is_form_encoded:
                del r_headers['Content-Type']
            r.url, headers, _ = self.client.sign(
                unicode(r.url), unicode(r.method), None, r_headers)
            if is_form_encoded:
                headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED

        r.prepare_headers(headers)
        r.url = to_native_string(r.url)
        log.debug('Updated url: %s', r.url)
        log.debug('Updated headers: %s', headers)
        log.debug('Updated body: %r', r.body)
        return r
Beispiel #19
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.

        content_type = r.headers.get('Content-Type'.encode('utf-8'), '')
        if not isinstance(content_type, unicode):
            content_type = content_type.decode('utf-8')

        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)

        if is_form_encoded or extract_params(r.body):
            r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            r.url, r.headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)
        else:
            # Omit body data in the signing of non form-encoded requests
            r.url, r.headers, _ = self.client.sign(
                unicode(r.url), unicode(r.method), None, r.headers)

        # Having the authorization header, key or value, in unicode will
        # result in UnicodeDecodeErrors when the request is concatenated
        # by httplib. This can easily be seen when attaching files.
        # Note that simply encoding the value is not enough since Python
        # saves the type of first key set. Thus we remove and re-add.
        # >>> d = {u'a':u'foo'}
        # >>> d['a'] = 'foo'
        # >>> d
        # { u'a' : 'foo' }
        u_header = unicode('Authorization')
        if u_header in r.headers:
            auth_header = r.headers[u_header].encode('utf-8')
            del r.headers[u_header]
            r.headers['Authorization'] = auth_header

        return r
Beispiel #20
0
    def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.
        """
        # Overwriting url is safe here as request will not modify it past
        # this point.
        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED
                           in r.headers.get('Content-Type', ''))

        if is_form_encoded or extract_params(r.body):
            r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            r.url, r.headers, r.body = self.client.sign(
                unicode(r.url), unicode(r.method), r.body or '', r.headers)
        else:
            # Omit body data in the signing of non form-encoded requests
            r.url, r.headers, _ = self.client.sign(unicode(r.url),
                                                   unicode(r.method), None,
                                                   r.headers)

        # Having the authorization header, key or value, in unicode will
        # result in UnicodeDecodeErrors when the request is concatenated
        # by httplib. This can easily be seen when attaching files.
        # Note that simply encoding the value is not enough since Python
        # saves the type of first key set. Thus we remove and re-add.
        # >>> d = {u'a':u'foo'}
        # >>> d['a'] = 'foo'
        # >>> d
        # { u'a' : 'foo' }
        u_header = unicode('Authorization')
        if u_header in r.headers:
            auth_header = r.headers[u_header].encode('utf-8')
            del r.headers[u_header]
            r.headers['Authorization'] = auth_header

        return r
Beispiel #21
0
 def test_extract_params_twotuple(self):
     self.assertItemsEqual(extract_params(PARAMS_TWOTUPLE), PARAMS_TWOTUPLE)
Beispiel #22
0
 def test_extract_params_dict(self):
     self.assertItemsEqual(extract_params(PARAMS_DICT), PARAMS_TWOTUPLE)
Beispiel #23
0
def collect_parameters(uri_query="", body=[], headers=None, exclude_oauth_signature=True, with_realm=False):
    """**Parameter Sources**

    Parameters starting with `oauth_` will be unescaped.

    Body parameters must be supplied as a dict, a list of 2-tuples, or a
    formencoded query string.

    Headers must be supplied as a dict.

    Per `section 3.4.1.3.1`_ of the spec.

    For example, the HTTP request::

        POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
        Host: example.com
        Content-Type: application/x-www-form-urlencoded
        Authorization: OAuth realm="Example",
            oauth_consumer_key="9djdj82h48djs9d2",
            oauth_token="kkk9d7dh3k39sjv7",
            oauth_signature_method="HMAC-SHA1",
            oauth_timestamp="137131201",
            oauth_nonce="7d8f3e4a",
            oauth_signature="djosJKDKJSD8743243%2Fjdk33klY%3D"

        c2&a3=2+q

    contains the following (fully decoded) parameters used in the
    signature base sting::

        +------------------------+------------------+
        |          Name          |       Value      |
        +------------------------+------------------+
        |           b5           |       =%3D       |
        |           a3           |         a        |
        |           c@           |                  |
        |           a2           |        r b       |
        |   oauth_consumer_key   | 9djdj82h48djs9d2 |
        |       oauth_token      | kkk9d7dh3k39sjv7 |
        | oauth_signature_method |     HMAC-SHA1    |
        |     oauth_timestamp    |     137131201    |
        |       oauth_nonce      |     7d8f3e4a     |
        |           c2           |                  |
        |           a3           |        2 q       |
        +------------------------+------------------+

    Note that the value of "b5" is "=%3D" and not "==".  Both "c@" and
    "c2" have empty values.  While the encoding rules specified in this
    specification for the purpose of constructing the signature base
    string exclude the use of a "+" character (ASCII code 43) to
    represent an encoded space character (ASCII code 32), this practice
    is widely used in "application/x-www-form-urlencoded" encoded values,
    and MUST be properly decoded, as demonstrated by one of the "a3"
    parameter instances (the "a3" parameter is used twice in this
    request).

    .. _`section 3.4.1.3.1`: http://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
    """
    headers = headers or {}
    params = []

    # The parameters from the following sources are collected into a single
    # list of name/value pairs:

    # *  The query component of the HTTP request URI as defined by
    #    `RFC3986, Section 3.4`_.  The query component is parsed into a list
    #    of name/value pairs by treating it as an
    #    "application/x-www-form-urlencoded" string, separating the names
    #    and values and decoding them as defined by
    #    `W3C.REC-html40-19980424`_, Section 17.13.4.
    #
    # .. _`RFC3986, Section 3.4`: http://tools.ietf.org/html/rfc3986#section-3.4
    # .. _`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424
    if uri_query:
        params.extend(urldecode(uri_query))

    # *  The OAuth HTTP "Authorization" header field (`Section 3.5.1`_) if
    #    present.  The header's content is parsed into a list of name/value
    #    pairs excluding the "realm" parameter if present.  The parameter
    #    values are decoded as defined by `Section 3.5.1`_.
    #
    # .. _`Section 3.5.1`: http://tools.ietf.org/html/rfc5849#section-3.5.1
    if headers:
        headers_lower = dict((k.lower(), v) for k, v in headers.items())
        authorization_header = headers_lower.get("authorization")
        if authorization_header is not None:
            params.extend(
                [i for i in utils.parse_authorization_header(authorization_header) if with_realm or i[0] != "realm"]
            )

    # *  The HTTP request entity-body, but only if all of the following
    #    conditions are met:
    #     *  The entity-body is single-part.
    #
    #     *  The entity-body follows the encoding requirements of the
    #        "application/x-www-form-urlencoded" content-type as defined by
    #        `W3C.REC-html40-19980424`_.

    #     *  The HTTP request entity-header includes the "Content-Type"
    #        header field set to "application/x-www-form-urlencoded".
    #
    # .._`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424

    # TODO: enforce header param inclusion conditions
    bodyparams = extract_params(body) or []
    params.extend(bodyparams)

    # ensure all oauth params are unescaped
    unescaped_params = []
    for k, v in params:
        if k.startswith("oauth_"):
            v = utils.unescape(v)
        unescaped_params.append((k, v))

    # The "oauth_signature" parameter MUST be excluded from the signature
    # base string if present.
    if exclude_oauth_signature:
        unescaped_params = list(filter(lambda i: i[0] != "oauth_signature", unescaped_params))

    return unescaped_params
Beispiel #24
0
def collect_parameters(uri_query='',
                       body=None,
                       headers=None,
                       exclude_oauth_signature=True,
                       with_realm=False):
    """
    Gather the request parameters from all the parameter sources.

    This function is used to extract all the parameters, which are then passed
    to ``normalize_parameters`` to produce one of the components that make up
    the *signature base string*.

    Parameters starting with `oauth_` will be unescaped.

    Body parameters must be supplied as a dict, a list of 2-tuples, or a
    form encoded query string.

    Headers must be supplied as a dict.

    The rules where the parameters must be sourced from are defined in
    `section 3.4.1.3.1`_ of RFC 5849.

    .. _`Sec 3.4.1.3.1`: https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
    """
    if body is None:
        body = []
    headers = headers or {}
    params = []

    # The parameters from the following sources are collected into a single
    # list of name/value pairs:

    # *  The query component of the HTTP request URI as defined by
    #    `RFC3986, Section 3.4`_.  The query component is parsed into a list
    #    of name/value pairs by treating it as an
    #    "application/x-www-form-urlencoded" string, separating the names
    #    and values and decoding them as defined by W3C.REC-html40-19980424
    #    `W3C-HTML-4.0`_, Section 17.13.4.
    #
    # .. _`RFC3986, Sec 3.4`: https://tools.ietf.org/html/rfc3986#section-3.4
    # .. _`W3C-HTML-4.0`: https://www.w3.org/TR/1998/REC-html40-19980424/
    if uri_query:
        params.extend(urldecode(uri_query))

    # *  The OAuth HTTP "Authorization" header field (`Section 3.5.1`_) if
    #    present.  The header's content is parsed into a list of name/value
    #    pairs excluding the "realm" parameter if present.  The parameter
    #    values are decoded as defined by `Section 3.5.1`_.
    #
    # .. _`Section 3.5.1`: https://tools.ietf.org/html/rfc5849#section-3.5.1
    if headers:
        headers_lower = {k.lower(): v for k, v in headers.items()}
        authorization_header = headers_lower.get('authorization')
        if authorization_header is not None:
            params.extend([
                i
                for i in utils.parse_authorization_header(authorization_header)
                if with_realm or i[0] != 'realm'
            ])

    # *  The HTTP request entity-body, but only if all of the following
    #    conditions are met:
    #     *  The entity-body is single-part.
    #
    #     *  The entity-body follows the encoding requirements of the
    #        "application/x-www-form-urlencoded" content-type as defined by
    #        W3C.REC-html40-19980424 `W3C-HTML-4.0`_.

    #     *  The HTTP request entity-header includes the "Content-Type"
    #        header field set to "application/x-www-form-urlencoded".
    #
    # .. _`W3C-HTML-4.0`: https://www.w3.org/TR/1998/REC-html40-19980424/

    # TODO: enforce header param inclusion conditions
    bodyparams = extract_params(body) or []
    params.extend(bodyparams)

    # ensure all oauth params are unescaped
    unescaped_params = []
    for k, v in params:
        if k.startswith('oauth_'):
            v = utils.unescape(v)
        unescaped_params.append((k, v))

    # The "oauth_signature" parameter MUST be excluded from the signature
    # base string if present.
    if exclude_oauth_signature:
        unescaped_params = list(
            filter(lambda i: i[0] != 'oauth_signature', unescaped_params))

    return unescaped_params
Beispiel #25
0
 def test_extract_params_blank_string(self):
     self.assertItemsEqual(extract_params(''), [])
Beispiel #26
0
 def test_extract_invalid(self):
     self.assertEqual(extract_params(object()), None)
     self.assertEqual(extract_params([('')]), None)
Beispiel #27
0
 def test_extract_params_empty_list(self):
     self.assertItemsEqual(extract_params([]), [])
Beispiel #28
0
 def test_extract_params_formencoded(self):
     self.assertEqual(extract_params(self.params_formencoded), self.params_twotuple)
Beispiel #29
0
 def test_extract_params_dict(self):
     self.assertItemsEqual(extract_params(PARAMS_DICT), PARAMS_TWOTUPLE)
Beispiel #30
0
 def test_extract_params_twotuple(self):
     self.assertItemsEqual(extract_params(PARAMS_TWOTUPLE), PARAMS_TWOTUPLE)
Beispiel #31
0
    async def __call__(self, r):
        """Add OAuth parameters to the request.

        Parameters may be included from the body if the content-type is
        urlencoded, if no content type is set a guess is made.

        Discussion:
        1. refactor to work with asks request objects which in particular
        do not maintain an up to date url including e.g. queries built
        from a params object?
        2. Need to understand oauth possibilities does signing ever
        change the url for example, if so asks might be broken as the
        url is not used for io?
        """

        # Overwriting url is safe here as request will not modify it past
        # this point.

        def str_(value,encoding):
            if isinstance(value,str): return value
            return str(value,encoding)

        log.debug('Signing request %s using client %s', r, self.client)

        # Paste over differences in requests and asks Request attribute names.
        r = MappedAttributesProxy(r,url='uri',body='data')

        if r.params:
            # oauth signing is based on full uri/url including the query
            # part, unfortunately asks doesn't provide this when the query
            # is passed via params, so we have to fix up here
            r.url = '{}?{}'.format(r.url.split('?')[0],r.path.split('?')[1])

        content_type = r.headers.get('Content-Type', '')
        if (not content_type and extract_params(r.body)
                or self.client.signature_type == SIGNATURE_TYPE_BODY):
            content_type = CONTENT_TYPE_FORM_URLENCODED
        if not isinstance(content_type, str):
            content_type = str(content_type,self.encoding)

        is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)

        log.debug('Including body in call to sign: %s',
                  is_form_encoded or self.force_include_body)

        if is_form_encoded:
            r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
            r.url, headers, r.body = self.client.sign(
                str_(r.url,self.encoding), str_(r.method,self.encoding), r.body or '', r.headers)
        if self.force_include_body:
            r.url, headers, r.body = self.client.sign(
                str_(r.url,self.encoding), str_(r.method,self.encoding), r.body or '', r.headers)
        else:
            r.url, headers, r.body = self.client.sign(
                str_(r.url,self.encoding), str_(r.method,self.encoding), None, r.headers)

        r.url = str_(r.url,self.encoding)
        log.debug('Updated url: %s', r.url)
        log.debug('Updated headers: %s', headers)
        log.debug('Updated body: %r', r.body)
        return headers
Beispiel #32
0
 def test_extract_params_formencoded(self):
     self.assertItemsEqual(extract_params(PARAMS_FORMENCODED),
                           PARAMS_TWOTUPLE)
Beispiel #33
0
 def test_extract_params_formencoded(self):
     self.assertItemsEqual(extract_params(PARAMS_FORMENCODED),
                           PARAMS_TWOTUPLE)
Beispiel #34
0
 def test_extract_params_blank_string(self):
     self.assertItemsEqual(extract_params(''), [])
Beispiel #35
0
 def test_extract_params_twotuple(self):
     self.assertEqual(extract_params(self.params_twotuple), self.params_twotuple)
Beispiel #36
0
 def test_extract_non_formencoded_string(self):
     self.assertEqual(extract_params('not a formencoded string'), None)
def collect_parameters(uri_query='',
                       body=[],
                       headers=None,
                       exclude_oauth_signature=True,
                       with_realm=False):
    """**Parameter Sources**

    Parameters starting with `oauth_` will be unescaped.

    Body parameters must be supplied as a dict, a list of 2-tuples, or a
    formencoded query string.

    Headers must be supplied as a dict.

    Per `section 3.4.1.3.1`_ of the spec.

    For example, the HTTP request::

        POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
        Host: example.com
        Content-Type: application/x-www-form-urlencoded
        Authorization: OAuth realm="Example",
            oauth_consumer_key="9djdj82h48djs9d2",
            oauth_token="kkk9d7dh3k39sjv7",
            oauth_signature_method="HMAC-SHA1",
            oauth_timestamp="137131201",
            oauth_nonce="7d8f3e4a",
            oauth_signature="djosJKDKJSD8743243%2Fjdk33klY%3D"

        c2&a3=2+q

    contains the following (fully decoded) parameters used in the
    signature base sting::

        +------------------------+------------------+
        |          Name          |       Value      |
        +------------------------+------------------+
        |           b5           |       =%3D       |
        |           a3           |         a        |
        |           c@           |                  |
        |           a2           |        r b       |
        |   oauth_consumer_key   | 9djdj82h48djs9d2 |
        |       oauth_token      | kkk9d7dh3k39sjv7 |
        | oauth_signature_method |     HMAC-SHA1    |
        |     oauth_timestamp    |     137131201    |
        |       oauth_nonce      |     7d8f3e4a     |
        |           c2           |                  |
        |           a3           |        2 q       |
        +------------------------+------------------+

    Note that the value of "b5" is "=%3D" and not "==".  Both "c@" and
    "c2" have empty values.  While the encoding rules specified in this
    specification for the purpose of constructing the signature base
    string exclude the use of a "+" character (ASCII code 43) to
    represent an encoded space character (ASCII code 32), this practice
    is widely used in "application/x-www-form-urlencoded" encoded values,
    and MUST be properly decoded, as demonstrated by one of the "a3"
    parameter instances (the "a3" parameter is used twice in this
    request).

    .. _`section 3.4.1.3.1`: http://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
    """
    headers = headers or {}
    params = []

    # The parameters from the following sources are collected into a single
    # list of name/value pairs:

    # *  The query component of the HTTP request URI as defined by
    #    `RFC3986, Section 3.4`_.  The query component is parsed into a list
    #    of name/value pairs by treating it as an
    #    "application/x-www-form-urlencoded" string, separating the names
    #    and values and decoding them as defined by
    #    `W3C.REC-html40-19980424`_, Section 17.13.4.
    #
    # .. _`RFC3986, Section 3.4`: http://tools.ietf.org/html/rfc3986#section-3.4
    # .. _`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424
    if uri_query:
        params.extend(urldecode(uri_query))

    # *  The OAuth HTTP "Authorization" header field (`Section 3.5.1`_) if
    #    present.  The header's content is parsed into a list of name/value
    #    pairs excluding the "realm" parameter if present.  The parameter
    #    values are decoded as defined by `Section 3.5.1`_.
    #
    # .. _`Section 3.5.1`: http://tools.ietf.org/html/rfc5849#section-3.5.1
    if headers:
        headers_lower = dict((k.lower(), v) for k, v in headers.items())
        authorization_header = headers_lower.get('authorization')
        if authorization_header is not None:
            params.extend([
                i
                for i in utils.parse_authorization_header(authorization_header)
                if with_realm or i[0] != 'realm'
            ])

    # *  The HTTP request entity-body, but only if all of the following
    #    conditions are met:
    #     *  The entity-body is single-part.
    #
    #     *  The entity-body follows the encoding requirements of the
    #        "application/x-www-form-urlencoded" content-type as defined by
    #        `W3C.REC-html40-19980424`_.

    #     *  The HTTP request entity-header includes the "Content-Type"
    #        header field set to "application/x-www-form-urlencoded".
    #
    # .._`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424

    # TODO: enforce header param inclusion conditions
    bodyparams = extract_params(body) or []
    params.extend(bodyparams)

    # ensure all oauth params are unescaped
    unescaped_params = []
    for k, v in params:
        if k.startswith('oauth_'):
            v = utils.unescape(v)
        unescaped_params.append((k, v))

    # The "oauth_signature" parameter MUST be excluded from the signature
    # base string if present.
    if exclude_oauth_signature:
        unescaped_params = list(
            filter(lambda i: i[0] != 'oauth_signature', unescaped_params))

    return unescaped_params
Beispiel #38
0
 def test_extract_non_formencoded_string(self):
     self.assertEqual(extract_params('not a formencoded string'), None)
Beispiel #39
0
 def test_extract_invalid(self):
     self.assertEqual(extract_params(object()), None)
     self.assertEqual(extract_params([('')]), None)
Beispiel #40
0
 def test_extract_invalid(self):
     self.assertIsNone(extract_params(object()))
     self.assertIsNone(extract_params([('')]))
Beispiel #41
0
 def test_extract_params_empty_list(self):
     self.assertItemsEqual(extract_params([]), [])