Example #1
0
    def request(self, method, url, **req_kwargs):
        '''
        A loose wrapper around Requests' :class:`~requests.sessions.Session`
        which injects OAuth 2.0 parameters.
        :param method: A string representation of the HTTP method to be used.
        :type method: str
        :param url: The resource to be requested.
        :type url: str
        :param \*\*req_kwargs: Keyworded args to be passed down to Requests.
        :type \*\*req_kwargs: dict
        '''
        req_kwargs.setdefault('params', {})

        url = self._set_url(url)

        if is_basestring(req_kwargs['params']):
            req_kwargs['params'] = dict(parse_qsl(req_kwargs['params']))

        if self.access_token and self.openid:
            req_kwargs['params'].update({
                'access_token': self.access_token,
                'openid': self.openid
            })

        req_kwargs.setdefault('timeout', OAUTH2_DEFAULT_TIMEOUT)

        resp = super(WXSession, self).request(method, url, **req_kwargs)
        if resp.encoding == 'ISO-8859-1':
            resp.encoding = 'utf-8'
        return resp
Example #2
0
    def request(self, method, url, bearer_auth=True, **req_kwargs):
        '''
        A loose wrapper around Requests' :class:`~requests.sessions.Session`
        which injects OAuth 2.0 parameters.

        :param method: A string representation of the HTTP method to be used.
        :type method: str
        :param url: The resource to be requested.
        :type url: str
        :param bearer_auth: Whether to use Bearer Authentication or not,
            defaults to `True`.
        :type bearer_auth: bool
        :param \*\*req_kwargs: Keyworded args to be passed down to Requests.
        :type \*\*req_kwargs: dict
        '''
        req_kwargs.setdefault('params', {})

        url = self._set_url(url)

        if is_basestring(req_kwargs['params']):
            req_kwargs['params'] = dict(parse_qsl(req_kwargs['params']))

        if bearer_auth and self.access_token is not None:
            bearer_token = 'Bearer {token}'.format(token=self.access_token)
            bearer_header = {'Authorization': bearer_token}
            req_kwargs.setdefault('headers', {})
            req_kwargs['headers'].update(bearer_header)
        else:
            req_kwargs['params'].update({self.access_token_key:
                                         self.access_token})

        req_kwargs.setdefault('timeout', OAUTH2_DEFAULT_TIMEOUT)

        return super(OAuth2Session, self).request(method, url, **req_kwargs)
Example #3
0
 def _get_lowered_d(self, d):
     lowered_d = {}
     for key in d:
         if is_basestring(key):
             lowered_d[key.lower()] = d[key]
         else:  # pragma: no cover
             lowered_d[key] = d[key]
     return lowered_d
Example #4
0
 def _get_lowered_d(self, d):
     lowered_d = {}
     for key in d:
         if is_basestring(key):
             lowered_d[key.lower()] = d[key]
         else:  # pragma: no cover
             lowered_d[key] = d[key]
     return lowered_d
Example #5
0
    def _normalize_request_parameters(self, oauth_params, req_kwargs):
        '''
        This process normalizes the request parameters as detailed in the OAuth
        1.0 spec.

        Additionally we apply a `Content-Type` header to the request of the
        `FORM_URLENCODE` type if the `Content-Type` was previously set, i.e. if
        this is a `POST` or `PUT` request. This ensures the correct header is
        set as per spec.

        Finally we sort the parameters in preparation for signing and return
        a URL encoded string of all normalized parameters.

        :param oauth_params: OAuth params to sign with.
        :type oauth_params: dict
        :param req_kwargs: Request kwargs to normalize.
        :type req_kwargs: dict
        '''
        normalized = []

        params = req_kwargs.get('params', {})
        data = req_kwargs.get('data', {})
        headers = req_kwargs.get('headers', {})

        # process request parameters
        for k, v in params.items():
            if v is not None:
                normalized += [(k, v)]

        # process request data
        if 'Content-Type' in headers and \
                headers['Content-Type'] == FORM_URLENCODED:
            for k, v in data.items():
                normalized += [(k, v)]

        # extract values from our list of tuples
        all_normalized = []
        for t in normalized:
            k, v = t
            if is_basestring(v) and not isinstance(v, bytes):
                v = v.encode('utf-8')
            all_normalized += [(k, v)]

        # add in the params from oauth_params for signing
        for k, v in oauth_params.items():
            if (k, v) in all_normalized:  # pragma: no cover
                continue
            all_normalized += [(k, v)]

        # sort the params as per the OAuth 1.0/a spec
        all_normalized.sort()

        # finally encode the params as a string
        return urlencode(all_normalized, True)\
            .replace('+', '%20')\
            .replace('%7E', '~')
Example #6
0
    def _normalize_request_parameters(self, oauth_params, req_kwargs):
        '''
        This process normalizes the request parameters as detailed in the OAuth
        1.0 spec.

        Additionally we apply a `Content-Type` header to the request of the
        `FORM_URLENCODE` type if the `Content-Type` was previously set, i.e. if
        this is a `POST` or `PUT` request. This ensures the correct header is
        set as per spec.

        Finally we sort the parameters in preparation for signing and return
        a URL encoded string of all normalized parameters.

        :param oauth_params: OAuth params to sign with.
        :type oauth_params: dict
        :param req_kwargs: Request kwargs to normalize.
        :type req_kwargs: dict
        '''
        normalized = []

        params = req_kwargs.get('params', {})
        data = req_kwargs.get('data', {})
        headers = req_kwargs.get('headers', {})

        # process request parameters
        for k, v in params.items():
            if v is not None:
                normalized += [(k, v)]

        # process request data
        if 'Content-Type' in headers and \
                headers['Content-Type'] == FORM_URLENCODED:
            for k, v in data.items():
                normalized += [(k, v)]

        # extract values from our list of tuples
        all_normalized = []
        for t in normalized:
            k, v = t
            if is_basestring(v) and not isinstance(v, bytes):
                v = v.encode('utf-8')
            all_normalized += [(k, v)]

        # add in the params from oauth_params for signing
        for k, v in oauth_params.items():
            if (k, v) in all_normalized:  # pragma: no cover
                continue
            all_normalized += [(k, v)]

        # sort the params as per the OAuth 1.0/a spec
        all_normalized.sort()

        # finally encode the params as a string
        return urlencode(all_normalized, True)\
            .replace('+', '%20')\
            .replace('%7E', '~')
Example #7
0
    def fake_request(self,
                     method,
                     url,
                     mock_request,
                     ofly_params,
                     user_id=None,
                     hash_meth='sha1',
                     **kwargs):
        mock_request.return_value = self.response

        user_id = user_id or self.service.user_id

        service = OflyService(self.app_id,
                              self.app_secret,
                              name='service',
                              authorize_url=self.authorize_url,
                              base_url=self.base_url)

        session = service.get_session(self.user_id)

        r = session.request(method,
                            url,
                            user_id=user_id,
                            hash_meth=hash_meth,
                            **deepcopy(kwargs))

        url = self.session._set_url(url)

        kwargs.setdefault('params', {})
        if is_basestring(kwargs['params']):
            kwargs['params'] = dict(parse_qsl(kwargs['params']))

        url_path = urlsplit(url).path

        signature_base_string = self.service.app_secret + url_path + '?'

        if len(kwargs['params']):
            signature_base_string += \
                self.fake_get_sorted_params(kwargs['params']) + '&'

        signature_base_string += self.fake_get_sorted_params(ofly_params)

        all_params = dict(tuple(ofly_params.items())
                          + tuple(kwargs['params'].items()))

        kwargs['params'] = self.fake_get_sorted_params(all_params)
        if not isinstance(kwargs['params'], bytes):
            kwargs['params'] = kwargs['params'].encode('utf-8')

        mock_request.assert_called_with(method,
                                        url,
                                        timeout=OFLY_DEFAULT_TIMEOUT,
                                        **kwargs)
        return r
Example #8
0
    def fake_request(self,
                     method,
                     url,
                     mock_request,
                     ofly_params,
                     user_id=None,
                     hash_meth='sha1',
                     **kwargs):
        mock_request.return_value = self.response

        user_id = user_id or self.service.user_id

        service = OflyService(self.app_id,
                              self.app_secret,
                              name='service',
                              authorize_url=self.authorize_url,
                              base_url=self.base_url)

        session = service.get_session(self.user_id)

        r = session.request(method,
                            url,
                            user_id=user_id,
                            hash_meth=hash_meth,
                            **deepcopy(kwargs))

        url = self.session._set_url(url)

        kwargs.setdefault('params', {})
        if is_basestring(kwargs['params']):
            kwargs['params'] = dict(parse_qsl(kwargs['params']))

        url_path = urlsplit(url).path

        signature_base_string = self.service.app_secret + url_path + '?'

        if len(kwargs['params']):
            signature_base_string += \
                self.fake_get_sorted_params(kwargs['params']) + '&'

        signature_base_string += self.fake_get_sorted_params(ofly_params)

        all_params = dict(
            tuple(ofly_params.items()) + tuple(kwargs['params'].items()))

        kwargs['params'] = self.fake_get_sorted_params(all_params)
        if not isinstance(kwargs['params'], bytes):
            kwargs['params'] = kwargs['params'].encode('utf-8')

        mock_request.assert_called_with(method,
                                        url,
                                        timeout=OFLY_DEFAULT_TIMEOUT,
                                        **kwargs)
        return r
Example #9
0
    def request(self,
                method,
                url,
                user_id=None,
                hash_meth='sha1',
                **req_kwargs):
        '''
        A loose wrapper around Requests' :class:`~requests.sessions.Session`
        which injects Ofly parameters.

        :param method: A string representation of the HTTP method to be used.
        :type method: str
        :param url: The resource to be requested.
        :type url: str
        :param hash_meth: The hash method to use for signing, defaults to
            "sha1".
        :type hash_meth: str
        :param user_id: The oflyUserid, defaults to `None`.
        :type user_id: str
        :param \*\*req_kwargs: Keyworded args to be passed down to Requests.
        :type \*\*req_kwargs: dict
        '''
        req_kwargs.setdefault('params', {})
        req_kwargs.setdefault('timeout', OFLY_DEFAULT_TIMEOUT)

        url = self._set_url(url)

        user_id = user_id or self.user_id
        assert user_id is not None, \
            'An oflyUserid must be provided as `user_id`.'

        if is_basestring(req_kwargs['params']):
            req_kwargs['params'] = dict(parse_qsl(req_kwargs['params']))

        req_kwargs['params'].update({'oflyUserid': user_id})

        params = OflySession.sign(url,
                                  self.app_id,
                                  self.app_secret,
                                  hash_meth=hash_meth,
                                  **req_kwargs['params'])

        # NOTE: Requests can't seem to handle unicode objects, instead we can
        # encode a string here.
        req_kwargs['params'] = params
        if not isinstance(req_kwargs['params'], bytes):
            req_kwargs['params'] = req_kwargs['params'].encode('utf-8')

        return super(OflySession, self).request(method, url, **req_kwargs)
Example #10
0
    def sign(self,
             consumer_secret,
             access_token_secret,
             method,
             url,
             oauth_params,
             req_kwargs):
        '''Sign request parameters.

        :param consumer_secret: RSA private key.
        :type consumer_secret: str or RSA._RSAobj
        :param access_token_secret: Unused.
        :type access_token_secret: str
        :param method: The method of this particular request.
        :type method: str
        :param url: The URL of this particular request.
        :type url: str
        :param oauth_params: OAuth parameters.
        :type oauth_params: dict
        :param req_kwargs: Keyworded args that will be sent to the request
            method.
        :type req_kwargs: dict
        '''
        url = self._remove_qs(url)

        oauth_params = \
            self._normalize_request_parameters(oauth_params, req_kwargs)
        parameters = map(self._escape, [method, url, oauth_params])

        # build a Signature Base String
        signature_base_string = b'&'.join(parameters)

        # resolve the key
        if is_basestring(consumer_secret):
            consumer_secret = self.RSA.importKey(consumer_secret)
        if not isinstance(consumer_secret, self.RSA._RSAobj):
            raise ValueError('invalid consumer_secret')

        # hash the string with RSA-SHA1
        s = self.PKCS1_v1_5.new(consumer_secret)
        # PyCrypto SHA.new requires an encoded byte string
        h = self.SHA.new(signature_base_string)
        hashed = s.sign(h)

        # return the signature
        return base64.b64encode(hashed).decode()
Example #11
0
    def sign(self,
             consumer_secret,
             access_token_secret,
             method,
             url,
             oauth_params,
             req_kwargs):
        '''Sign request parameters.

        :param consumer_secret: RSA private key.
        :type consumer_secret: str or RSA._RSAobj
        :param access_token_secret: Unused.
        :type access_token_secret: str
        :param method: The method of this particular request.
        :type method: str
        :param url: The URL of this particular request.
        :type url: str
        :param oauth_params: OAuth parameters.
        :type oauth_params: dict
        :param req_kwargs: Keyworded args that will be sent to the request
            method.
        :type req_kwargs: dict
        '''
        url = self._remove_qs(url)

        oauth_params = \
            self._normalize_request_parameters(oauth_params, req_kwargs)
        parameters = map(self._escape, [method, url, oauth_params])

        # build a Signature Base String
        signature_base_string = b'&'.join(parameters)

        # resolve the key
        if is_basestring(consumer_secret):
            consumer_secret = self.RSA.importKey(consumer_secret)
        if not isinstance(consumer_secret, self.RSA._RSAobj):
            raise ValueError("invalid consumer_secret")

        # hash the string with RSA-SHA1
        s = self.PKCS1_v1_5.new(consumer_secret)
        # PyCrypto SHA.new requires an encoded byte string
        h = self.SHA.new(signature_base_string)
        hashed = s.sign(h)

        # return the signature
        return base64.b64encode(hashed).decode()
Example #12
0
    def fake_request(self,
                     method,
                     url,
                     mock_request,
                     bearer_auth=False,
                     **kwargs):
        mock_request.return_value = self.response

        url = self.session._set_url(url)

        service = OAuth2Service(self.client_id,
                                self.client_secret,
                                access_token_url=self.access_token_url,
                                authorize_url=self.authorize_url,
                                base_url=self.base_url)

        session = service.get_session(self.access_token)
        r = session.request(method,
                            url,
                            bearer_auth=bearer_auth,
                            **deepcopy(kwargs))

        kwargs.setdefault('params', {})

        if is_basestring(kwargs.get('params', {})):
            kwargs['params'] = dict(parse_qsl(kwargs['params']))

        if bearer_auth and self.access_token is not None:
            bearer_token = 'Bearer {token}'.format(token=self.access_token)
            bearer_header = {'Authorization': bearer_token}
            kwargs.setdefault('headers', {})
            kwargs['headers'].update(bearer_header)
        else:
            kwargs['params'].update({'access_token': self.access_token})

        mock_request.assert_called_with(method,
                                        url,
                                        timeout=OAUTH2_DEFAULT_TIMEOUT,
                                        **kwargs)
        return r
    def fake_request(self,
                     method,
                     url,
                     mock_request,
                     bearer_auth=False,
                     **kwargs):
        mock_request.return_value = self.response

        url = self.session._set_url(url)

        service = OAuth2Service(self.client_id,
                                self.client_secret,
                                access_token_url=self.access_token_url,
                                authorize_url=self.authorize_url,
                                base_url=self.base_url)

        session = service.get_session(self.access_token)
        r = session.request(method,
                            url,
                            bearer_auth=bearer_auth,
                            **deepcopy(kwargs))

        kwargs.setdefault('params', {})

        if is_basestring(kwargs.get('params', {})):
            kwargs['params'] = dict(parse_qsl(kwargs['params']))

        if bearer_auth and self.access_token is not None:
            auth = mock_request.call_args[1]['auth']
            self.assertEqual(auth.access_token, self.access_token)
            kwargs['auth'] = auth
        else:
            kwargs['params'].update({'access_token':
                                     self.access_token})

        mock_request.assert_called_with(method,
                                        url,
                                        timeout=OAUTH2_DEFAULT_TIMEOUT,
                                        **kwargs)
        return r
Example #14
0
    def request(self,
                method,
                url,
                header_auth=False,
                realm='',
                **req_kwargs):
        '''
        A loose wrapper around Requests' :class:`~requests.sessions.Session`
        which injects OAuth 1.0/a parameters.

        :param method: A string representation of the HTTP method to be used.
        :type method: str
        :param url: The resource to be requested.
        :type url: str
        :param header_auth: Authentication via header, defaults to `False.`
        :type header_auth: bool
        :param realm: The auth header realm, defaults to ``""``.
        :type realm: str
        :param \*\*req_kwargs: Keyworded args to be passed down to Requests.
        :type \*\*req_kwargs: dict
        '''
        req_kwargs.setdefault('headers', {})
        req_kwargs['headers'] = CaseInsensitiveDict(req_kwargs['headers'])

        url = self._set_url(url)

        entity_method = method.upper() in ENTITY_METHODS
        if entity_method:
            req_kwargs['headers'].setdefault('Content-Type', FORM_URLENCODED)

        form_urlencoded = \
            req_kwargs['headers'].get('Content-Type') == FORM_URLENCODED

        # inline string conversion
        if is_basestring(req_kwargs.get('params')):
            req_kwargs['params'] = dict(parse_qsl(req_kwargs['params']))

        if is_basestring(req_kwargs.get('data')) and form_urlencoded:
            req_kwargs['data'] = dict(parse_qsl(req_kwargs['data']))

        req_kwargs.setdefault('timeout', OAUTH1_DEFAULT_TIMEOUT)

        oauth_params = self._get_oauth_params(req_kwargs)

        # ensure we always create new instances of dictionary elements
        for key, value in req_kwargs.items():
            if isinstance(value, dict):
                req_kwargs[key] = deepcopy(value)

        # sign the request
        oauth_params['oauth_signature'] = \
            self.signature.sign(self.consumer_secret,
                                self.access_token_secret,
                                method,
                                url,
                                oauth_params,
                                req_kwargs)

        if header_auth and not 'oauth_signature' in \
                req_kwargs['headers'].get('Authorization', ''):
            header = self._get_auth_header(oauth_params, realm)
            req_kwargs['headers'].update({'Authorization': header})
        elif entity_method and not 'oauth_signature' in \
                (req_kwargs.get('data') or {}):
            req_kwargs['data'] = req_kwargs.get('data') or {}

            # If we have a urlencoded entity-body we should pass the OAuth
            # parameters on this body. However, if we do not, then we need to
            # pass these over the request URI, i.e. on params.
            #
            # See:
            #
            #   http://tools.ietf.org/html/rfc5849#section-3.5.2
            #
            # and:
            #
            #   http://tools.ietf.org/html/rfc5849#section-3.5.3
            if form_urlencoded:
                req_kwargs['data'].update(oauth_params)
            else:
                req_kwargs.setdefault('params', {})
                req_kwargs['params'].update(oauth_params)
        elif not 'oauth_signature' in url:
            req_kwargs.setdefault('params', {})
            req_kwargs['params'].update(oauth_params)

        return super(OAuth1Session, self).request(method, url, **req_kwargs)
Example #15
0
    def setdefault(self, key, default):
        if is_basestring(key):
            key = key.lower()

        super(CaseInsensitiveDict, self).setdefault(key, default)
Example #16
0
    def setdefault(self, key, default):
        if is_basestring(key):
            key = key.lower()

        super(CaseInsensitiveDict, self).setdefault(key, default)
Example #17
0
    def fake_request(self,
                     method,
                     url,
                     mock_request,
                     mock_random,
                     mock_time,
                     mock_sig,
                     header_auth=False,
                     realm='',
                     **kwargs):
        fake_random = 1
        fake_time = 1
        fake_sig = 'foo'
        fake_sig_meth = 'HMAC-SHA1'
        fake_nonce = sha1(str(fake_random).encode('ascii')).hexdigest()

        mock_request.return_value = self.response
        mock_random.return_value = fake_random
        mock_time.return_value = fake_time
        mock_sig.return_value = fake_sig

        method = method
        url = self.session._set_url(url)

        service = OAuth1Service(self.consumer_key,
                                self.consumer_secret,
                                name='service',
                                request_token_url=self.request_token_url,
                                access_token_url=self.access_token_url,
                                authorize_url=self.authorize_url,
                                base_url=self.base_url)

        session = service.get_session((self.access_token,
                                       self.access_token_secret))

        r = session.request(method,
                            url,
                            header_auth=header_auth,
                            realm=realm,
                            **deepcopy(kwargs))

        kwargs.setdefault('headers', {})
        kwargs['headers'] = CaseInsensitiveDict(kwargs['headers'])

        entity_method = method.upper() in ENTITY_METHODS
        if entity_method:
            kwargs['headers'].setdefault('Content-Type', FORM_URLENCODED)

        form_urlencoded = \
            kwargs['headers'].get('Content-Type') == FORM_URLENCODED

        if is_basestring(kwargs.get('params')):
            kwargs['params'] = dict(parse_qsl(kwargs['params']))

        if is_basestring(kwargs.get('data')) and form_urlencoded:
            kwargs['data'] = dict(parse_qsl(kwargs['data']))

        oauth_params = {'oauth_consumer_key': session.consumer_key,
                        'oauth_nonce': fake_nonce,
                        'oauth_signature_method': fake_sig_meth,
                        'oauth_timestamp': fake_time,
                        'oauth_token': self.access_token,
                        'oauth_version': session.VERSION,
                        'oauth_signature': fake_sig}

        if header_auth:
            auth = mock_request.call_args[1]['auth']
            auth_header = self.fake_get_auth_header(oauth_params, realm=realm)
            self.assertEqual(auth(requests.Request()).headers['Authorization'],
                             auth_header)
            kwargs['auth'] = auth
        elif entity_method:
            kwargs['data'] = kwargs.get('data') or {}

            if form_urlencoded:
                kwargs['data'].update(oauth_params)
            else:
                kwargs.setdefault('params', {})
                kwargs['params'].update(oauth_params)
        else:
            kwargs.setdefault('params', {})
            kwargs['params'].update(**oauth_params)

        mock_request.assert_called_with(method,
                                        url,
                                        timeout=OAUTH1_DEFAULT_TIMEOUT,
                                        **kwargs)
        return r