Example #1
0
class OAuth1(object):
    """Signs the request using OAuth 1 (RFC5849)"""

    def __init__(
        self,
        client_key,
        client_secret=None,
        resource_owner_key=None,
        resource_owner_secret=None,
        callback_uri=None,
        signature_method=SIGNATURE_HMAC,
        signature_type=SIGNATURE_TYPE_AUTH_HEADER,
        rsa_key=None,
        verifier=None,
        decoding="utf-8",
    ):

        try:
            signature_type = signature_type.upper()
        except AttributeError:
            pass

        self.client = Client(
            client_key,
            client_secret,
            resource_owner_key,
            resource_owner_secret,
            callback_uri,
            signature_method,
            signature_type,
            rsa_key,
            verifier,
            decoding=decoding,
        )

    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
Example #2
0
    def build_oauth_request(self, method, uri, credentials, timestamp,
                            parameters=None, as_query=True):
        """Build an oauth request given some credentials."""

        # oauthlib is requiring the timestamp to be a string, because
        # it tries to escape all the parameters.
        oauth_client = Client(credentials['consumer_key'],
                              credentials['consumer_secret'],
                              credentials['token'],
                              credentials['token_secret'],
                              signature_method=(SIGNATURE_PLAINTEXT
                                                if self.oauth_sign_plain
                                                else SIGNATURE_HMAC),
                              signature_type=(SIGNATURE_TYPE_QUERY
                                              if as_query
                                              else SIGNATURE_TYPE_AUTH_HEADER),
                              timestamp=str(timestamp))

        try:
            url, signed_headers, body = oauth_client.sign(
                uri, method, parameters if parameters is not None else {},
                {'Content-Type': 'application/x-www-form-urlencoded'})
        except ValueError:
            url, signed_headers, body = oauth_client.sign(uri, method)

        return url, signed_headers, body
Example #3
0
class OAuth1(object):
    """Signs the request using OAuth 1 (RFC5849)"""
    def __init__(self,
                 client_key,
                 client_secret=None,
                 resource_owner_key=None,
                 resource_owner_secret=None,
                 callback_uri=None,
                 signature_method=SIGNATURE_HMAC,
                 signature_type=SIGNATURE_TYPE_AUTH_HEADER,
                 rsa_key=None,
                 verifier=None):

        try:
            signature_type = signature_type.upper()
        except AttributeError:
            pass

        self.client = Client(client_key, client_secret, resource_owner_key,
                             resource_owner_secret, callback_uri,
                             signature_method, signature_type, rsa_key,
                             verifier)

    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
Example #4
0
class OAuth1(object):
    """Signs the request using OAuth 1 (RFC5849)"""
    def __init__(self,
                 client_key,
                 client_secret=None,
                 resource_owner_key=None,
                 resource_owner_secret=None,
                 callback_uri=None,
                 signature_method=SIGNATURE_HMAC,
                 signature_type=SIGNATURE_TYPE_AUTH_HEADER,
                 rsa_key=None,
                 verifier=None,
                 decoding='utf-8'):

        try:
            signature_type = signature_type.upper()
        except AttributeError:
            pass

        self.client = Client(client_key,
                             client_secret,
                             resource_owner_key,
                             resource_owner_secret,
                             callback_uri,
                             signature_method,
                             signature_type,
                             rsa_key,
                             verifier,
                             decoding=decoding)

    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
Example #5
0
class OAuth1(object):
    """Signs the request using OAuth 1 (RFC5849)"""
    def __init__(self, client_key,
            client_secret=None,
            resource_owner_key=None,
            resource_owner_secret=None,
            callback_uri=None,
            signature_method=SIGNATURE_HMAC,
            signature_type=SIGNATURE_TYPE_AUTH_HEADER,
            rsa_key=None, verifier=None,
            decoding='utf-8'):

        try:
            signature_type = signature_type.upper()
        except AttributeError:
            pass

        self.client = Client(client_key, client_secret, resource_owner_key,
            resource_owner_secret, callback_uri, signature_method,
            signature_type, rsa_key, verifier, decoding=decoding)

    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
Example #6
0
def make_api_call(consumer_key,
                  consumer_secret,
                  access_token_key,
                  access_token_secret,
                  method,
                  params,
                  api_url,
                  body=None,
                  headers=None):

    headers = dict(headers or {})
    method = method.upper()
    params = dict(params, format='json')
    if method == 'GET':
        full_url = api_url + "?" + urllib.urlencode(params)
    elif method == 'POST':
        full_url = api_url
        body = urllib.urlencode(params)
        headers['Content-Type'] = 'application/x-www-form-urlencoded'
    else:
        raise ValueError('unsupported HTTP method %r' % method)

    client = OAClient(consumer_key, client_secret=consumer_secret,
                      resource_owner_key=access_token_key,
                      resource_owner_secret=access_token_secret)
    full_url, headers, body = client.sign(full_url, method, body, headers)

    client = httplib2.Http()
    client.disable_ssl_certificate_validation = True

    resp, content = client.request(full_url,
                                   method=method,
                                   body=body,
                                   headers=headers)
    return content
Example #7
0
  def __init__(self, handler, **kwargs):
    U1Request.__init__(self, handler, kwargs)
    self.message.type = protocol_pb2.Message.AUTH_REQUEST
    self.states = {protocol_pb2.Message.AUTH_AUTHENTICATED: self.authenticated,
                   protocol_pb2.Message.ROOT: self.root}
    self.end_msg_type = protocol_pb2.Message.ROOT
    # retrieve our OAuth credentials from file
    def credentials_from_file():
      """Extracts the OAuth credentials from file"""
      with open(AuthRequest.CREDENTIALS_FILE) as f:
        jsoncreds = json.loads(f.read())
        return jsoncreds

    oauth_creds = credentials_from_file()
    # Sign the message with oauth
    client = Client(oauth_creds["consumer_key"], oauth_creds["consumer_secret"],
                    oauth_creds["token"], oauth_creds["token_secret"],
                    signature_method=SIGNATURE_PLAINTEXT,
                    signature_type=SIGNATURE_TYPE_QUERY)
    url, headers, body = client.sign('http://server')
    # Parse out the authentication parameters from the query string.
    auth_parameters = dict((name, value) for name, value in
                           parse_qsl(urlparse(url).query)
                           if name.startswith('oauth_'))
    # add the authentication informations to the protobuf
    for key, value in auth_parameters.items():
      newparam = self.message.auth_parameters.add() # create a new parameter
      newparam.name = key
      newparam.value = value
Example #8
0
    def oauth1(self):
        auth_url = self.url_base + '/session'

        oauth1_client = Client(
            self.server_token['consumer_key'],
            client_secret=self.server_token['consumer_secret'],
            resource_owner_key=self.server_token['access_token'],
            resource_owner_secret=self.server_token['access_secret'])

        uri, headers, body = oauth1_client.sign(auth_url)

        request = Request(auth_url)

        request.add_header('Authorization', headers['Authorization'])
        request.add_header('Content-Type', 'application/json;charset=UTF8')
        request.add_header('X-Server-Protocol-Version', '2')

        response = urlopen(request).read()

        # TODO: catch HTTP errors here, do something useful

        resp_dict = json.loads(response)

        self.session_token = resp_dict['auth_session_token']

        if self.new_session_callback:
            self.new_session_callback(self.session_token)

        return self.session_token
Example #9
0
def get_access_token(consumer_key,
                     consumer_secret,
                     req_token_key,
                     req_token_secret,
                     verifier,
                     access_token_url,
                     validate_certs=True):
    method = 'GET'
    params = {'format': 'json', 'oauth_callback': 'oob'}
    # they're really serious about that oob
    full_url = access_token_url + "&" + urllib.urlencode(params)
    client = OAClient(consumer_key,
                      client_secret=consumer_secret,
                      resource_owner_key=req_token_key,
                      resource_owner_secret=req_token_secret,
                      verifier=verifier,
                      signature_type=SIGNATURE_TYPE_QUERY)
    full_url, headers, body = client.sign(full_url, method)

    client = httplib2.Http()
    client.disable_ssl_certificate_validation = not validate_certs
    resp, content = client.request(full_url, method=method)
    try:
        resp_dict = json.loads(content)
        acc_token_key, acc_token_secret = resp_dict['key'], resp_dict['secret']
    except:
        raise ValueError('access token step failed: %s\n\nheaders, etc.: %s'
                         % (content, pformat(resp)))
    return acc_token_key, acc_token_secret
Example #10
0
    def oauth1(self):
        auth_url = self.url_base + '/session'

        oauth1_client = Client(
            self.server_token['consumer_key'],
            client_secret=self.server_token['consumer_secret'],
            resource_owner_key=self.server_token['access_token'],
            resource_owner_secret=self.server_token['access_secret'])

        uri, headers, body = oauth1_client.sign(auth_url)

        request = Request(auth_url)

        request.add_header('Authorization', headers['Authorization'])
        request.add_header('Content-Type', 'application/json;charset=UTF8')
        request.add_header('X-Server-Protocol-Version', '2')

        response = urlopen(request).read()

        # TODO: catch HTTP errors here, do something useful

        resp_dict = json.loads(response)

        self.session_token = resp_dict['auth_session_token']

        if self.new_session_callback:
            self.new_session_callback(self.session_token)

        return self.session_token
Example #11
0
 def sign_request(self, url, method, body, headers):
     """Sign a request with OAuth credentials."""
     # 2012-11-19 BAW: In order to preserve API backward compatibility,
     # convert empty string body to None.  The old python-oauth library
     # would treat the empty string as "no body", but python-oauthlib
     # requires None.
     if not body:
         content_type = headers.get('Content-Type')
         if content_type == 'application/x-www-form-urlencoded':
             body = ''
         else:
             body = None
     # Import oauthlib here so that you don't need it if you're not going
     # to use it.  Plan B: move this out into a separate oauth module.
     from oauthlib.oauth1 import Client
     from oauthlib.oauth1.rfc5849 import SIGNATURE_PLAINTEXT
     oauth_client = Client(self.consumer_key,
                           self.consumer_secret,
                           self.token_key,
                           self.token_secret,
                           signature_method=SIGNATURE_PLAINTEXT,
                           realm=self.oauth_realm)
     uri, signed_headers, body = oauth_client.sign(url, method, body,
                                                   headers)
     headers.update(signed_headers)
Example #12
0
    def __init__(self, handler, **kwargs):
        U1Request.__init__(self, handler, kwargs)
        self.message.type = protocol_pb2.Message.AUTH_REQUEST
        self.states = {
            protocol_pb2.Message.AUTH_AUTHENTICATED: self.authenticated,
            protocol_pb2.Message.ROOT: self.root
        }
        self.end_msg_type = protocol_pb2.Message.ROOT

        # retrieve our OAuth credentials from file
        def credentials_from_file():
            """Extracts the OAuth credentials from file"""
            with open(AuthRequest.CREDENTIALS_FILE) as f:
                jsoncreds = json.loads(f.read())
                return jsoncreds

        oauth_creds = credentials_from_file()
        # Sign the message with oauth
        client = Client(oauth_creds["consumer_key"],
                        oauth_creds["consumer_secret"],
                        oauth_creds["token"],
                        oauth_creds["token_secret"],
                        signature_method=SIGNATURE_PLAINTEXT,
                        signature_type=SIGNATURE_TYPE_QUERY)
        url, headers, body = client.sign('http://server')
        # Parse out the authentication parameters from the query string.
        auth_parameters = dict(
            (name, value) for name, value in parse_qsl(urlparse(url).query)
            if name.startswith('oauth_'))
        # add the authentication informations to the protobuf
        for key, value in auth_parameters.items():
            newparam = self.message.auth_parameters.add(
            )  # create a new parameter
            newparam.name = key
            newparam.value = value
Example #13
0
def launch(CFG, url, post, status=200) :
    header = {'Content-Type' : 'application/x-www-form-urlencoded'}
    client = Client(CFG.oauth_consumer_key, client_secret=CFG.oauth_secret, signature_type='BODY')
    uri, headers, body = client.sign(url, 'POST', post, header)
    print('\nLaunching to',url,end=' ')
    r = requests.post(url, data=body, headers=headers, allow_redirects=False)
    if ( r.status_code == 302 or r.status_code == 303 ) :
        new_url = r.headers.get('Location', False)
        if new_url is False:
            print('No Location header found on redirect')
            dumpr(r)
            abort()

        error_url = post.get('launch_presentation_return_url', False)
        if ( new_url.startswith(error_url) ) :
            if ( status == 200 ) :
                print('Expected a successful launch')
                dumpr(r)
                abort()
            print('Received 302 - Success')
            return r

        print('\nFollowing redirect', new_url,end=' ')
        r = requests.get(new_url, cookies=r.cookies)

    if ( status != 200 ) :
        print('Expected a failed launch')
        dumpr(r)
        abort()
    print('Received 200 - Success')
    return r
Example #14
0
    def get_login_url(self, request):
        client = Client(client_key = unicode(self.get_client_key()), 
            client_secret = unicode(self.get_client_secret()), 
            resource_owner_key = u'', 
            resource_owner_secret = u'',
            callback_uri = unicode(self.get_redirect_url(request)),
            signature_type = SIGNATURE_TYPE_QUERY)

        token_url, _token_body, _token_headers = client.sign(unicode(self.get_request_token_uri()))

        res = requests.get(token_url)
        res_data = urlparse.parse_qs(res.text)

        if 'oauth_token' not in res_data:
            raise BackendError("Oauth provider didn't return access_token. %s" % res.text)

        request.session[OAUTH_TOKEN_SECRET_KEY] = res_data['oauth_token_secret'][0]

        authorization_url = self.get_authorize_token_uri()
        authorization_params = {'oauth_token': res_data['oauth_token'][0], 'oauth_callback': self.get_redirect_url(request)}

        url_parts = list(urlparse.urlparse(authorization_url))

        query = dict(urlparse.parse_qsl(url_parts[4]))
        query.update(authorization_params)

        url_parts[4] = urllib.urlencode(query)

        return urlparse.urlunparse(url_parts)
Example #15
0
File: oauth.py Project: d42/JD
class OauthRequests:
    def __init__(self, secret_key, client_key, defaults=None):
        self.defaults = {
            "devId": "c55b00b5-dead-beef-cafe-babefac3b001",
            "user-agent": "Samsung - 4.4.2 - API 19 - 1024x600 Android 4.4.2",
            "locale": "en"
        }

        if defaults:
            self.defaults.update(defaults)
        self.secret_key = secret_key
        self.client_key = client_key
        self.oauth = Client(client_key, client_secret=secret_key)

    @cached_request
    def __call__(self, url, params=None):
        params = params or {}
        url = url_set_params(url, params)
        url, headers, _ = self.oauth.sign(url)
        headers.update(self.defaults)
        req = requests.get(url, headers=headers)

        if req.status_code != 200:
            logging.error("code %d: %s", req.status_code, req.text)
        return req
Example #16
0
    def get_session(self, **kwargs):
        if self.get_backend_name() in kwargs:
            auth_obj = kwargs[self.get_backend_name()]
            request = auth_obj

            if 'oauth_token' not in request.REQUEST:
                raise BackendError("Oauth provider didn't return access_token")

            oauth_token = request.REQUEST.get('oauth_token')
            oauth_verifier = request.REQUEST.get('oauth_verifier')

            client = Client(client_key = unicode(self.get_client_key()), 
                client_secret = unicode(self.get_client_secret()), 
                resource_owner_key = unicode(oauth_token), 
                resource_owner_secret = unicode(request.session[OAUTH_TOKEN_SECRET_KEY]),
                verifier = unicode(oauth_verifier),
                signature_type = SIGNATURE_TYPE_QUERY)

            access_url, _access_body, _access_header = client.sign(unicode(self.get_access_token_uri()))

            res = requests.get(access_url)
            res_data = urlparse.parse_qs(res.text)

            if 'oauth_token' not in res_data:
                raise BackendError("Oauth provider didn't return access_token. %s" % res.text)

            access_tokens = {
                'oauth_token_secret': res_data['oauth_token_secret'][0],
                'oauth_token': res_data['oauth_token'][0]
            }

            return self._get_session(**access_tokens)
Example #17
0
 def sign_get_query(self, url=None):
     client = Client(self.service.consumer_key,
         client_secret=self.service.consumer_secret,
         signature_method=SIGNATURE_HMAC,
         signature_type=SIGNATURE_TYPE_QUERY)
     uri = update_url_params(url or self.service.service.url, self.parameters)
     query, headers, body = client.sign(uri, http_method="GET")
     return query
Example #18
0
File: lti.py Project: Vilz92/a-plus
 def sign_get_query(self, url=None):
     client = Client(self.service.consumer_key,
                     client_secret=self.service.consumer_secret,
                     signature_method=SIGNATURE_HMAC,
                     signature_type=SIGNATURE_TYPE_QUERY)
     uri = update_url_params(url or self.service.service.url,
                             self.parameters)
     query, headers, body = client.sign(uri, http_method="GET")
     return query
Example #19
0
 def test_enforce_ssl(self):
     """Ensure SSL is enforced by default."""
     v = RequestValidator()
     e = BaseEndpoint(v)
     c = Client('foo')
     u, h, b = c.sign('http://example.com')
     r = e._create_request(u, 'GET', b, h)
     self.assertRaises(errors.InsecureTransportError,
                       e._check_transport_security, r)
Example #20
0
 def test_enforce_ssl(self):
     """Ensure SSL is enforced by default."""
     v = RequestValidator()
     e = BaseEndpoint(v)
     c = Client('foo')
     u, h, b = c.sign('http://example.com')
     r = e._create_request(u, 'GET', b, h)
     self.assertRaises(errors.InsecureTransportError,
             e._check_transport_security, r)
Example #21
0
 def sign_post_parameters(self, url=None):
     client = Client(self.service.consumer_key,
         client_secret=self.service.consumer_secret,
         signature_method=SIGNATURE_HMAC,
         signature_type=SIGNATURE_TYPE_BODY)
     uri, headers, body = client.sign(url or self.service.url,
         http_method="POST",
         body=self.parameters,
         headers={"Content-Type": "application/x-www-form-urlencoded"})
     return urldecode(body)
Example #22
0
 def sign_post_parameters(self, url=None):
     client = Client(self.service.consumer_key,
         client_secret=self.service.consumer_secret,
         signature_method=SIGNATURE_HMAC,
         signature_type=SIGNATURE_TYPE_BODY)
     uri, headers, body = client.sign(self._get_url(url),
         http_method="POST",
         body=self.parameters,
         headers={"Content-Type": "application/x-www-form-urlencoded"})
     return urldecode(body)
Example #23
0
 def sign_get_query(self, url=None):
     client = Client(self.service.consumer_key,
         client_secret=self.service.consumer_secret,
         signature_method=SIGNATURE_HMAC,
         signature_type=SIGNATURE_TYPE_QUERY)
     uri = update_url_params(self._get_url(url), self.parameters)
     try:
         query, headers, body = client.sign(uri, http_method="GET")
     except ValueError as e:
         raise ValueError("Invalid url %r for %r: %s" % (uri, self.service, e))
     return query
Example #24
0
 async def _connect(
     self, method, endpoint, params={}, headers=None, body=None
 ):
     oauth_client = OAuthClient(self.consumer_key, self.consumer_secret,
                                self.access_token, self.access_token_secret)
     url = f"https://stream.twitter.com/1.1/{endpoint}.json"
     url = str(URL(url).with_query(sorted(params.items())))
     url, headers, body = oauth_client.sign(
         url, http_method=method, headers=headers, body=body
     )
     await super()._connect(method, url, headers=headers, body=body)
Example #25
0
 def sign_get_query(self, url=None):
     client = Client(self.service.consumer_key,
         client_secret=self.service.consumer_secret,
         signature_method=SIGNATURE_HMAC,
         signature_type=SIGNATURE_TYPE_QUERY)
     uri = update_url_params(self._get_url(url), self.parameters)
     try:
         query, headers, body = client.sign(uri, http_method="GET")
     except ValueError as e:
         raise ValueError("Invalid url %r for %r: %s" % (uri, self.service, e))
     return query
Example #26
0
 def getAuthorization(self, method, url, callback=None, verifier=None):
     client = Client(
         safe_unicode(self.consumer_key),
         safe_unicode(self.consumer_secret),
         safe_unicode(self.key),
         safe_unicode(self.secret),
         callback_uri=safe_unicode(callback),
         verifier=safe_unicode(verifier),
     )
     safe_method = safe_unicode(method)
     safe_url = safe_unicode(url)
     # data is omitted because no www-form-encoded data
     _, header, _ = client.sign(safe_url, safe_method)
     return header
Example #27
0
def xauth(base_url_template=DEFAULT_READER_URL_TEMPLATE, **xargs):
    """
    Returns an OAuth token tuple that can be used with clients.ReaderClient.

    :param base_url_template: Template for generating Readability API urls.
    :param consumer_key:  Readability consumer key, otherwise read from READABILITY_CONSUMER_KEY.
    :param consumer_secret: Readability consumer secret, otherwise read from READABILITY_CONSUMER_SECRET.
    :param username: A username, otherwise read from READABILITY_USERNAME.
    :param password: A password, otherwise read from READABILITY_PASSWORD.

    """
    consumer_key = xargs.get('consumer_key') or required_from_env(
        'READABILITY_CONSUMER_KEY')
    consumer_secret = xargs.get('consumer_secret') or required_from_env(
        'READABILITY_CONSUMER_SECRET')
    username = xargs.get('username') or required_from_env(
        'READABILITY_USERNAME')
    password = xargs.get('password') or required_from_env(
        'READABILITY_PASSWORD')

    client = Client(consumer_key,
                    client_secret=consumer_secret,
                    signature_type='BODY')
    url = base_url_template.format(ACCESS_TOKEN_URL)
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    params = {
        'x_auth_username': username,
        'x_auth_password': password,
        'x_auth_mode': 'client_auth'
    }

    uri, headers, body = client.sign(url,
                                     http_method='POST',
                                     body=urlencode(params),
                                     headers=headers)

    response = requests.post(uri, data=body)
    logger.debug('POST to %s.', uri)

    token = parse_qs(response.content)
    try:
        # The indexes below are a little weird. parse_qs above gives us
        # back a dict where each value is a list. We want the first value
        # in those lists.
        token = (token[b'oauth_token'][0].decode(),
                 token[b'oauth_token_secret'][0].decode())
    except KeyError:
        raise ValueError('Invalid Credentials.')

    return token
 def getAuthorization(self, method, url, callback=None, verifier=None):
     client = Client(
         safe_unicode(self.consumer_key),
         safe_unicode(self.consumer_secret),
         safe_unicode(self.key),
         safe_unicode(self.secret),
         callback_uri=safe_unicode(callback),
         verifier=safe_unicode(verifier),
     )
     safe_method = safe_unicode(method)
     safe_url = safe_unicode(url)
     # data is omitted because no www-form-encoded data
     _, header, _ = client.sign(safe_url, safe_method)
     return header
Example #29
0
    def getAuthorization(self, request):
        client = Client(
            safe_unicode(self.client_key),
            safe_unicode(self.client_secret),
            safe_unicode(self.key),
            safe_unicode(self.secret),
            callback_uri=safe_unicode(self.callback),
            verifier=safe_unicode(self.verifier),
        )
        method = safe_unicode(request.get_method())
        url = safe_unicode(request.get_full_url())

        # data is omitted because no www-form-encoded data
        uri, headers, body = client.sign(url, method)
        return headers['Authorization']
Example #30
0
    def getAuthorization(self, request):
        client = Client(
            safe_unicode(self.client_key),
            safe_unicode(self.client_secret),
            safe_unicode(self.key),
            safe_unicode(self.secret),
            callback_uri=safe_unicode(self.callback),
            verifier=safe_unicode(self.verifier),
        )
        method = safe_unicode(request.get_method())
        url = safe_unicode(request.get_full_url())

        # data is omitted because no www-form-encoded data
        uri, headers, body = client.sign(url, method)
        return headers["Authorization"]
Example #31
0
class YelpAsyncAPI:
    def __init__(self):
        # set oauth
        consumer_key = os.environ["YELP_CONSUMER_KEY"]
        consumer_secret = os.environ['YELP_CONSUMER_SECRET']
        token = os.environ['YELP_TOKEN']
        token_secret = os.environ['YELP_TOKEN_SECRET']
        if consumer_key is None or consumer_secret is None or token is None or token_secret is None:
            raise NoKeyError
        self.client = Client( consumer_key,
            client_secret=consumer_secret,
            resource_owner_key=token,
            resource_owner_secret=token_secret)

    @asyncio.coroutine
    def send_query(self, uri, params=None):
        if params:
            params = self.clean_params(params)
        logger.debug("yelp send:%s", params)
        uri = uri + "?" + params
        uri, headers, _ = self.client.sign(uri)

        response = yield from aiohttp.request(
            'GET',
            uri,
            headers=headers)

        data = json.loads((yield from response.read()).decode('utf8'))
        if 'error' in data:
            logger.debug(data)
            raise YelpError(msg=data['error']['text'])
        return data

    def clean_params(self, params):
        clean_params = {}
        for key in params:
            value = params[key]
            if value:
                clean_params[key] = str(value).replace(' ', '+')
        return urlencode(clean_params)

    @asyncio.coroutine
    def search(self, **kwargs):
        SEARCH_URI = 'http://api.yelp.com/v2/search'
        params=kwargs

        data = yield from self.send_query(SEARCH_URI, params=params)
        return data['businesses']
def xauth(base_url_template=DEFAULT_READER_URL_TEMPLATE, **xargs):
    """
    Returns an OAuth token tuple that can be used with clients.ReaderClient.

    :param base_url_template: Template for generating Readability API urls.
    :param consumer_key:  Readability consumer key, otherwise read from READABILITY_CONSUMER_KEY.
    :param consumer_secret: Readability consumer secret, otherwise read from READABILITY_CONSUMER_SECRET.
    :param username: A username, otherwise read from READABILITY_USERNAME.
    :param password: A password, otherwise read from READABILITY_PASSWORD.

    """
    consumer_key = xargs.get('consumer_key') or required_from_env('READABILITY_CONSUMER_KEY')
    consumer_secret = xargs.get('consumer_secret') or required_from_env('READABILITY_CONSUMER_SECRET')
    username = xargs.get('username') or required_from_env('READABILITY_USERNAME')
    password = xargs.get('password') or required_from_env('READABILITY_PASSWORD')

    client = Client(consumer_key, client_secret=consumer_secret, signature_type='BODY')
    url = base_url_template.format(ACCESS_TOKEN_URL)
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    params = {
        'x_auth_username': username,
        'x_auth_password': password,
        'x_auth_mode': 'client_auth'
    }

    uri, headers, body = client.sign(url,
        http_method='POST',
        body=urlencode(params),
        headers=headers)

    response = requests.post(uri, data=body)
    logger.debug('POST to %s.', uri)

    token = parse_qs(response.content)
    try:
        # The indexes below are a little weird. parse_qs above gives us
        # back a dict where each value is a list. We want the first value
        # in those lists.
        token = (token[b'oauth_token'][0].decode(), token[b'oauth_token_secret'][0].decode())
    except KeyError:
        raise ValueError('Invalid Credentials.')

    return token
Example #33
0
def _sign_lti_message(body, key, secret, url):
    client = Client(client_key=key, client_secret=secret)

    __, headers, __ = client.sign(
        unicode(url),
        http_method=u'POST',
        body=body,
        headers={'Content-Type': 'application/x-www-form-urlencoded'})

    auth_header = headers['Authorization'][len('OAuth '):]
    auth = dict([
        param.strip().replace('"', '').split('=')
        for param in auth_header.split(',')
    ])

    body['oauth_nonce'] = auth['oauth_nonce']
    body['oauth_signature'] = auth['oauth_signature']
    body['oauth_timestamp'] = auth['oauth_timestamp']
    body['oauth_signature_method'] = auth['oauth_signature_method']
    body['oauth_version'] = auth['oauth_version']
Example #34
0
    def _sign_lti_message(self, body, key, secret, url):
        client = Client(client_key=key, client_secret=secret)

        __, headers, __ = client.sign(
            url,
            http_method=u"POST",
            body=body,
            headers={"Content-Type": "application/x-www-form-urlencoded"},
        )

        auth_header = headers["Authorization"][len("OAuth "):]
        auth = dict([
            param.strip().replace('"', "").split("=")
            for param in auth_header.split(",")
        ])

        body["oauth_nonce"] = auth["oauth_nonce"]
        body["oauth_signature"] = auth["oauth_signature"]
        body["oauth_timestamp"] = auth["oauth_timestamp"]
        body["oauth_signature_method"] = auth["oauth_signature_method"]
        body["oauth_version"] = auth["oauth_version"]
Example #35
0
def _sign_lti_message(body, key, secret, url):
    client = Client(
        client_key=key,
        client_secret=secret
    )

    __, headers, __ = client.sign(
        unicode(url),
        http_method=u'POST',
        body=body,
        headers={'Content-Type': 'application/x-www-form-urlencoded'}
    )

    auth_header = headers['Authorization'][len('OAuth '):]
    auth = dict([param.strip().replace('"', '').split('=') for param in auth_header.split(',')])

    body['oauth_nonce'] = auth['oauth_nonce']
    body['oauth_signature'] = auth['oauth_signature']
    body['oauth_timestamp'] = auth['oauth_timestamp']
    body['oauth_signature_method'] = auth['oauth_signature_method']
    body['oauth_version'] = auth['oauth_version']
Example #36
0
class OAuth1(object):
    '''gets an OAuth 1 (RFC5849) header'''
    authstr = 'Authorization'

    def __init__(self,
                 callback_uri=None,
                 signature_method=SIGNATURE_HMAC,
                 signature_type=SIGNATURE_TYPE_AUTH_HEADER,
                 rsa_key=None,
                 verifier=None,
                 decoding='utf-8',
                 **kwargs):
        kwargs = DotDot(kwargs)
        if signature_type:
            signature_type = signature_type.upper()

        self.client = Client(kwargs.consumer_key,
                             kwargs.consumer_secret,
                             kwargs.access_token_key,
                             kwargs.access_token_secret,
                             callback_uri,
                             signature_method,
                             signature_type,
                             rsa_key,
                             verifier,
                             decoding=decoding)

    def get_oath_header(self, url, http_method, parms):
        '''call it to get a recalculated OAuth1 header

        :param str url: request URL
        :param str http_method: request method GET|POST|PUT etc.......
        :param dict parms: request parameters

        :return: an OAuth 1 header
        '''
        rt = self.client.sign('%s?%s' % (url, urlencode(parms)),
                              http_method=http_method)
        return "%s: %s" % (self.authstr, rt[1][self.authstr].encode('utf-8'))
Example #37
0
 def sign_request(self, url, method, body, headers):
     """Sign a request with OAuth credentials."""
     # 2012-11-19 BAW: In order to preserve API backward compatibility,
     # convert empty string body to None.  The old python-oauth library
     # would treat the empty string as "no body", but python-oauthlib
     # requires None.
     if not body:
         content_type = headers.get('Content-Type')
         if content_type == 'application/x-www-form-urlencoded':
             body = ''
         else:
             body = None
     # Import oauthlib here so that you don't need it if you're not going
     # to use it.  Plan B: move this out into a separate oauth module.
     from oauthlib.oauth1 import Client
     from oauthlib.oauth1.rfc5849 import SIGNATURE_PLAINTEXT
     oauth_client = Client(self.consumer_key, self.consumer_secret,
                           self.token_key, self.token_secret,
                           signature_method=SIGNATURE_PLAINTEXT,
                           realm=self.oauth_realm)
     uri, signed_headers, body = oauth_client.sign(
         url, method, body, headers)
     headers.update(signed_headers)
Example #38
0
class OAuth1(object):
    '''gets an OAuth 1 (RFC5849) header'''
    authstr = 'Authorization'

    def __init__(
            self,
            callback_uri=None,
            signature_method=SIGNATURE_HMAC,
            signature_type=SIGNATURE_TYPE_AUTH_HEADER,
            rsa_key=None,
            verifier=None,
            decoding='utf-8',
            **kwargs):
        kwargs = DotDot(kwargs)
        if signature_type:
            signature_type = signature_type.upper()

        self.client = Client(
            kwargs.consumer_key,
            kwargs.consumer_secret,
            kwargs.access_token_key,
            kwargs.access_token_secret,
            callback_uri, signature_method,
            signature_type, rsa_key, verifier, decoding=decoding)

    def get_oath_header(self, url, http_method, parms):
        '''call it to get a recalculated OAuth1 header

        :param str url: request URL
        :param str http_method: request method GET|POST|PUT etc.......
        :param dict parms: request parameters

        :return: an OAuth 1 header
        '''
        rt = self.client.sign('%s?%s' % (url, urlencode(parms)), http_method=http_method)
        return "%s: %s" % (self.authstr, rt[1][self.authstr].encode('utf-8'))
Example #39
0
    def _get_oauth_headers(self, method, url, data=None, headers=None):
        """Basic wrapper around oauthlib that we use for Twitter and Flickr."""
        # "Client" == "Consumer" in oauthlib parlance.
        key = self._account.consumer_key
        secret = self._account.consumer_secret

        # "resource_owner" == secret and token.
        resource_owner_key = self._get_access_token()
        resource_owner_secret = self._account.secret_token
        oauth_client = Client(key, secret, resource_owner_key,
                              resource_owner_secret)

        headers = headers or {}
        if data is not None:
            headers['Content-Type'] = 'application/x-www-form-urlencoded'

        # All we care about is the headers, which will contain the
        # Authorization header necessary to satisfy OAuth.
        uri, headers, body = oauth_client.sign(url,
                                               body=data,
                                               headers=headers or {},
                                               http_method=method)

        return headers
Example #40
0
    async def _connect(self,
                       method,
                       endpoint,
                       params={},
                       headers=None,
                       body=None):
        error_count = 0
        # https://developer.twitter.com/en/docs/twitter-api/v1/tweets/filter-realtime/guides/connecting
        stall_timeout = 90
        network_error_wait = network_error_wait_step = 0.25
        network_error_wait_max = 16
        http_error_wait = http_error_wait_start = 5
        http_error_wait_max = 320
        http_420_error_wait_start = 60

        oauth_client = OAuthClient(self.consumer_key, self.consumer_secret,
                                   self.access_token, self.access_token_secret)

        if self.session is None or self.session.closed:
            self.session = aiohttp.ClientSession(
                headers={"User-Agent": self.user_agent},
                timeout=aiohttp.ClientTimeout(sock_read=stall_timeout))

        url = f"https://stream.twitter.com/1.1/{endpoint}.json"
        url = str(URL(url).with_query(sorted(params.items())))

        try:
            while error_count <= self.max_retries:
                request_url, request_headers, request_body = oauth_client.sign(
                    url, method, body, headers)
                try:
                    async with self.session.request(method,
                                                    request_url,
                                                    headers=request_headers,
                                                    data=request_body,
                                                    proxy=self.proxy) as resp:
                        if resp.status == 200:
                            error_count = 0
                            http_error_wait = http_error_wait_start
                            network_error_wait = network_error_wait_step

                            await self.on_connect()

                            async for line in resp.content:
                                line = line.strip()
                                if line:
                                    await self.on_data(line)
                                else:
                                    await self.on_keep_alive()

                            await self.on_closed(resp)
                        else:
                            await self.on_request_error(resp.status)

                            error_count += 1

                            if resp.status == 420:
                                if http_error_wait < http_420_error_wait_start:
                                    http_error_wait = http_420_error_wait_start

                            await asyncio.sleep(http_error_wait)

                            http_error_wait *= 2
                            if resp.status != 420:
                                if http_error_wait > http_error_wait_max:
                                    http_error_wait = http_error_wait_max
                except (aiohttp.ClientConnectionError,
                        aiohttp.ClientPayloadError) as e:
                    await self.on_connection_error()

                    await asyncio.sleep(network_error_wait)

                    network_error_wait += network_error_wait_step
                    if network_error_wait > network_error_wait_max:
                        network_error_wait = network_error_wait_max
        except asyncio.CancelledError:
            return
        except Exception as e:
            await self.on_exception(e)
        finally:
            await self.session.close()
            await self.on_disconnect()
Example #41
0
def SignedTestRequest(form=None, consumer=None, token=None, method=None,
        url=None, callback=None, timestamp=None, verifier=None,
        signature_type='AUTH_HEADER', raw_body=None,
        *a, **kw):
    """\
    Creates a signed TestRequest
    """

    def safe_unicode(s):
        # I really really hate oauthlib's insistence on using unicode
        # on things that are really bytes.
        if isinstance(s, str):
            return unicode(s)

        return s

    if not consumer:
        raise ValueError('consumer must be provided to build a signed request')

    if form is None:
        form = {}

    result = TestRequest(form=form, url=url, method=method, *a, **kw)
    if raw_body:
        result.stdin.write(raw_body)

    url = url or result.getURL()
    url = safe_unicode(url)
    method = method and safe_unicode(method) or safe_unicode(result.method)
    timestamp = timestamp or unicode(int(time()))

    token_key = token and token.key
    token_secret = token and token.secret

    client = Client(
        safe_unicode(consumer.key),
        safe_unicode(consumer.secret),
        safe_unicode(token_key),
        safe_unicode(token_secret),
        safe_unicode(callback),
        verifier=safe_unicode(verifier),
        timestamp=timestamp,
        signature_type=signature_type,
    )

    if result.getHeader('Content-Type') == 'application/x-www-form-urlencoded':
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        url_signed, headers, body = client.sign(url, method,
            body=raw_body, headers=headers)
    else:
        url_signed, headers, body = client.sign(url, method)

    # lazy not importing oauthlib tokens.
    if signature_type == 'AUTH_HEADER':
        result._auth = headers['Authorization']
        return result
    elif signature_type == 'QUERY':
        qs = urlparse.urlsplit(url_signed).query
        result = TestRequest(form=form, url=url, QUERY_STRING=qs, *a, **kw)
        if raw_body:
            result.stdin.write(raw_body)
        return result
Example #42
0
    def get_common_objects(self):
        super().get_common_objects()
        user = self.request.user

        # Determine user ID.
        student_id = "aplusuid%d" % (user.pk)
        if self.profile.student_id:
            student_id = self.profile.student_id

        # MD5 the user id so that the real student id and names or emails
        # are not linked in external services.
        student_id = hashlib.md5(student_id.encode('utf-8')).hexdigest()

        # Determine user role.
        role = "Student"
        if self.is_teacher:
            role = "Instructor"
        elif self.is_assistant:
            role = "TA,TeachingAssistant"

        parameters = {

            "lti_version": "LTI-1p0",
            "lti_message_type": "basic-lti-launch-request",

            "resource_link_id": "aplus%d" % (self.service.pk),
            "resource_link_title": self.menu_item.label,

            # User session.
            "user_id": student_id,
            "roles": role,
            "lis_person_name_full": "%s %s" % (user.first_name, user.last_name),
            "lis_person_name_given": user.first_name,
            "lis_person_name_family": user.last_name,
            "lis_person_contact_email_primary": user.email,

            # Selected course.
            "context_id": self.request.get_host() \
                + self.instance.get_absolute_url(),
            "context_title": self.course.name,
            "context_label": self.course.code,

            "launch_presentation_locale": get_language(),

            "tool_consumer_instance_guid": self.request.get_host() + "/aplus",
            "tool_consumer_instance_name": "A+ LMS",
        }
        headers = {
            "Content-Type": "application/x-www-form-urlencoded",
        }

        # Sign the request using OAuth.
        client = Client(self.service.consumer_key,
            client_secret=self.service.consumer_secret,
            signature_method=SIGNATURE_HMAC,
            signature_type=SIGNATURE_TYPE_BODY)
        uri, headers, body = client.sign(self.service.url,
            http_method="POST",
            body=parameters,
            headers=headers)
        self.url = uri
        self.parameters = urldecode(body)
        self.note("url", "parameters")
Example #43
0
class BaseEndpointTest(TestCase):
    def setUp(self):
        self.validator = MagicMock(spec=RequestValidator)
        self.validator.allowed_signature_methods = ['HMAC-SHA1']
        self.validator.timestamp_lifetime = 600
        self.endpoint = RequestTokenEndpoint(self.validator)
        self.client = Client('foo', callback_uri='https://c.b/cb')
        self.uri, self.headers, self.body = self.client.sign(
            'https://i.b/request_token')

    def test_ssl_enforcement(self):
        uri, headers, _ = self.client.sign('http://i.b/request_token')
        h, b, s = self.endpoint.create_request_token_response(uri,
                                                              headers=headers)
        self.assertEqual(s, 400)
        self.assertIn('insecure_transport_protocol', b)

    def test_missing_parameters(self):
        h, b, s = self.endpoint.create_request_token_response(self.uri)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_signature_methods(self):
        headers = {}
        headers['Authorization'] = self.headers['Authorization'].replace(
            'HMAC', 'RSA')
        h, b, s = self.endpoint.create_request_token_response(self.uri,
                                                              headers=headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_signature_method', b)

    def test_invalid_version(self):
        headers = {}
        headers['Authorization'] = self.headers['Authorization'].replace(
            '1.0', '2.0')
        h, b, s = self.endpoint.create_request_token_response(self.uri,
                                                              headers=headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_expired_timestamp(self):
        headers = {}
        for pattern in ('12345678901', '4567890123', '123456789K'):
            headers['Authorization'] = sub(r'timestamp="\d*k?"',
                                           'timestamp="%s"' % pattern,
                                           self.headers['Authorization'])
            h, b, s = self.endpoint.create_request_token_response(
                self.uri, headers=headers)
            self.assertEqual(s, 400)
            self.assertIn('invalid_request', b)

    def test_client_key_check(self):
        self.validator.check_client_key.return_value = False
        h, b, s = self.endpoint.create_request_token_response(
            self.uri, headers=self.headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_noncecheck(self):
        self.validator.check_nonce.return_value = False
        h, b, s = self.endpoint.create_request_token_response(
            self.uri, headers=self.headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_enforce_ssl(self):
        """Ensure SSL is enforced by default."""
        v = RequestValidator()
        e = BaseEndpoint(v)
        c = Client('foo')
        u, h, b = c.sign('http://example.com')
        r = e._create_request(u, 'GET', b, h)
        self.assertRaises(errors.InsecureTransportError,
                          e._check_transport_security, r)

    def test_multiple_source_params(self):
        """Check for duplicate params"""
        v = RequestValidator()
        e = BaseEndpoint(v)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                          'https://a.b/?oauth_signature_method=HMAC-SHA1',
                          'GET', 'oauth_version=foo', URLENCODED)
        headers = {'Authorization': 'OAuth oauth_signature="foo"'}
        headers.update(URLENCODED)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                          'https://a.b/?oauth_signature_method=HMAC-SHA1',
                          'GET', 'oauth_version=foo', headers)
        headers = {'Authorization': 'OAuth oauth_signature_method="foo"'}
        headers.update(URLENCODED)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                          'https://a.b/', 'GET', 'oauth_signature=foo',
                          headers)

    def test_duplicate_params(self):
        """Ensure params are only supplied once"""
        v = RequestValidator()
        e = BaseEndpoint(v)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                          'https://a.b/?oauth_version=a&oauth_version=b',
                          'GET', None, URLENCODED)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                          'https://a.b/', 'GET',
                          'oauth_version=a&oauth_version=b', URLENCODED)

    def test_mandated_params(self):
        """Ensure all mandatory params are present."""
        v = RequestValidator()
        e = BaseEndpoint(v)
        r = e._create_request(
            'https://a.b/', 'GET',
            'oauth_signature=a&oauth_consumer_key=b&oauth_nonce', URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                          e._check_mandatory_parameters, r)

    def test_oauth_version(self):
        """OAuth version must be 1.0 if present."""
        v = RequestValidator()
        e = BaseEndpoint(v)
        r = e._create_request(
            'https://a.b/', 'GET',
            ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
             'oauth_timestamp=a&oauth_signature_method=RSA-SHA1&'
             'oauth_version=2.0'), URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                          e._check_mandatory_parameters, r)

    def test_oauth_timestamp(self):
        """Check for a valid UNIX timestamp."""
        v = RequestValidator()
        e = BaseEndpoint(v)

        # Invalid timestamp length, must be 10
        r = e._create_request(
            'https://a.b/', 'GET',
            ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
             'oauth_version=1.0&oauth_signature_method=RSA-SHA1&'
             'oauth_timestamp=123456789'), URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                          e._check_mandatory_parameters, r)

        # Invalid timestamp age, must be younger than 10 minutes
        r = e._create_request(
            'https://a.b/', 'GET',
            ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
             'oauth_version=1.0&oauth_signature_method=RSA-SHA1&'
             'oauth_timestamp=1234567890'), URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                          e._check_mandatory_parameters, r)

        # Timestamp must be an integer
        r = e._create_request(
            'https://a.b/', 'GET',
            ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
             'oauth_version=1.0&oauth_signature_method=RSA-SHA1&'
             'oauth_timestamp=123456789a'), URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                          e._check_mandatory_parameters, r)

    def test_case_insensitive_headers(self):
        """Ensure headers are case-insensitive"""
        v = RequestValidator()
        e = BaseEndpoint(v)
        r = e._create_request(
            'https://a.b', 'POST',
            ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
             'oauth_version=1.0&oauth_signature_method=RSA-SHA1&'
             'oauth_timestamp=123456789a'), URLENCODED)
        self.assertIsInstance(r.headers, CaseInsensitiveDict)

    def test_signature_method_validation(self):
        """Ensure valid signature method is used."""

        body = ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
                'oauth_version=1.0&oauth_signature_method=%s&'
                'oauth_timestamp=1234567890')

        uri = 'https://example.com/'

        class HMACValidator(RequestValidator):
            @property
            def allowed_signature_methods(self):
                return (SIGNATURE_HMAC, )

        v = HMACValidator()
        e = BaseEndpoint(v)
        r = e._create_request(uri, 'GET', body % 'RSA-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'PLAINTEXT', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'shibboleth', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)

        class RSAValidator(RequestValidator):
            @property
            def allowed_signature_methods(self):
                return (SIGNATURE_RSA, )

        v = RSAValidator()
        e = BaseEndpoint(v)
        r = e._create_request(uri, 'GET', body % 'HMAC-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'PLAINTEXT', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'shibboleth', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)

        class PlainValidator(RequestValidator):
            @property
            def allowed_signature_methods(self):
                return (SIGNATURE_PLAINTEXT, )

        v = PlainValidator()
        e = BaseEndpoint(v)
        r = e._create_request(uri, 'GET', body % 'HMAC-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'RSA-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'shibboleth', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                          e._check_mandatory_parameters, r)
Example #44
0
async def _call_twitter_api_once(
    client: httpx.Client,
    api_endpoint: str,
    params: Dict[str, str],
    *,
    oauth_client: oauth1.Client,
    get_n_tweets: Callable[[Dict[str, Any]], int],
    get_max_tweet_id: Callable[[Dict[str, Any]], int],
    get_next_token: Callable[[Dict[str, Any]], Union[int, Optional[str]]],
) -> Tuple[Optional[ResultPart], Optional[Union[int, str]]]:
    """Send a single request to the Twitter API; return (ResultPart, next_token).

    If the result has no tweets, return `None`.

    Otherwise, wrap the result in a `ResultPart`.

    Undefined behavior if `get_n_tweets()` raises an error, or if Twitter
    returns non-JSON.

    For Twitter API v1, "get_next_token" can return the minimum tweet ID.
    Callers can use that to construct a "max_id" for a subsequent request.
    """
    HEADERS = {"Accept": "application/json"}

    api_params = urlencode(list(sorted(params.items())))
    url = f"https://api.twitter.com/{api_endpoint}?{api_params}"
    url, headers, body = oauth_client.sign(url, headers=HEADERS)

    body = io.BytesIO()
    try:
        result = await download(url,
                                body,
                                headers=headers,
                                httpx_client=client)
    except HttpErrorNotSuccess as err:
        return (
            ResultPart(
                "API-ERROR.lz4",
                mtime=parsedate_to_datetime(
                    err.response.headers["date"]).timestamp(),
                api_endpoint=api_endpoint,
                api_params=api_params,
                http_status=str(err.response.status_code),
                body=_lz4_compress(body.getbuffer()),
            ),
            None,
        )
    except HttpError as err:
        return (
            ResultPart(
                "NETWORK-ERROR.json.lz4",
                mtime=datetime.datetime.utcnow().timestamp(),
                api_endpoint=api_endpoint,
                api_params=api_params,
                body=_lz4_compress(
                    _utf8_json_encode(err.i18n_message._asdict())),
            ),
            None,
        )

    # missing HTTP date header? Undefined behavior
    date_header_value = next(value for key, value in result.headers
                             if key.lower() == "date")
    # not valid UTF-8 JSON? Undefined behavior
    data = json.loads(str(body.getvalue(), encoding="utf-8"))
    # missing JSON fields, or not Array response? Undefined behavior
    n_tweets = get_n_tweets(data)
    if n_tweets == 0:
        return None, None  # don't write this API response to the tarfile
    max_tweet_id = get_max_tweet_id(data)
    next_token = get_next_token(data)

    return (
        ResultPart(
            "%d.json.lz4" % max_tweet_id,
            # invalid date format? Undefined behavior
            mtime=parsedate_to_datetime(date_header_value).timestamp(),
            api_endpoint=api_endpoint,
            api_params=api_params,
            http_status=str(result.status_code),
            n_tweets=n_tweets,
            body=_lz4_compress(body.getbuffer()),
        ),
        next_token,
    )
Example #45
0
class TumblrClient(object):
    api_base_url = 'https://api.tumblr.com/v2/'
    request_token_url = 'https://www.tumblr.com/oauth/request_token'
    authorization_url = 'https://www.tumblr.com/oauth/authorize'
    access_token_url = 'https://www.tumblr.com/oauth/access_token'

    def __init__(self, consumer_key: str, consumer_secret: str, resource_owner_key: Optional[str] = None,
                 resource_owner_secret: Optional[str] = None, callback_uri: Optional[str] = None,
                 oauth_verifier: Optional[str] = None, debug_mode: Optional[bool] = None):
        if debug_mode:
            self.session = aiohttp.ClientSession(trace_configs=[AIOTumblrDebugger(logger=log)])
        else:
            self.session = aiohttp.ClientSession()

        self.oauth_client = Client(
            client_key=consumer_key,
            client_secret=consumer_secret,
            resource_owner_key=resource_owner_key,
            resource_owner_secret=resource_owner_secret,
            callback_uri=callback_uri,
            verifier=oauth_verifier,
        )

    async def fetch_request_token(self) -> Dict[str, str]:
        log.debug(f'Fetching request token...')
        _, signed_headers, _ = self.oauth_client.sign(self.request_token_url, 'POST')
        log.debug(f'Signed headers: {signed_headers}')

        resp = await self.session.post(self.request_token_url, headers=signed_headers)
        log.debug(f'Response: {resp.status} {resp.reason}')
        log.debug(f'To: {resp.method} {resp.real_url.human_repr()}')
        log.debug(f'Requested as: {resp.request_info.method} {resp.request_info.real_url.human_repr()}')
        log.debug(f'Request headers: {resp.request_info.headers}')

        token_raw = await resp.text()
        log.debug(f'Token response: {token_raw}')
        token = dict(urldecode(token_raw))

        self.oauth_client.resource_owner_key = token['oauth_token']
        self.oauth_client.resource_owner_secret = token['oauth_token_secret']

        # Set callback to None for future signing calls
        self.oauth_client.callback_uri = None

        return token

    def fetch_authorization_url(self, request_token: str = None) -> str:
        if not request_token:
            request_token = self.oauth_client.resource_owner_key

        return f'{self.authorization_url}?oauth_token={request_token}'

    def parse_authorization_response(self, url: str) -> Dict[str, str]:
        token = dict(urldecode(urlparse(url).query))

        self.oauth_client.resource_owner_key = token['oauth_token']
        self.oauth_client.verifier = token['oauth_verifier']

        return token

    async def fetch_access_token(self, verifier: Optional[str] = None) -> Dict[str, str]:
        if verifier:
            self.oauth_client.verifier = verifier
        if not getattr(self.oauth_client, 'verifier', None):
            raise ValueError('No client verifier set.')  # TODO: implement own exceptions

        log.debug(f'Fetching access token...')
        _, signed_headers, _ = self.oauth_client.sign(self.access_token_url, 'POST')
        log.debug(f'Signed headers: {signed_headers}')

        resp = await self.session.post(self.access_token_url, headers=signed_headers)
        log.debug(f'Response: {resp.status} {resp.reason}')
        log.debug(f'To: {resp.method} {resp.real_url.human_repr()}')
        log.debug(f'Requested as: {resp.request_info.method} {resp.request_info.real_url.human_repr()}')
        log.debug(f'Request headers: {resp.request_info.headers}')

        token_raw = await resp.text()
        log.debug(f'Token response: {token_raw}')
        token = dict(urldecode(token_raw))

        self.oauth_client.resource_owner_key = token['oauth_token']
        self.oauth_client.resource_owner_secret = token['oauth_token_secret']

        # Unset verifier
        self.oauth_client.verifier = None

        return token

    async def signed_request(self, method: str, endpoint: str, params: Optional[List[Tuple[str, str]]] = None,
                             data: Optional[Dict[str, str]] = None, json: Optional[Any] = None,
                             headers: Optional[Dict[str, str]] = None, **kwargs) -> aiohttp.ClientResponse:
        url = self.api_base_url + endpoint

        if data:
            _, signed_headers, _ = self.oauth_client.sign(
                add_params_to_uri(url, params), http_method=method, body=data, headers=headers
            )
            return await self.session.request(method, url, params=params, data=data, headers=signed_headers)
        elif json:
            # Since it is JSON, body apparently doesn't matter when signing
            _, signed_headers, _ = self.oauth_client.sign(
                add_params_to_uri(url, params), http_method=method, headers=headers
            )
            return await self.session.request(method, url, params=params, json=json, headers=signed_headers)
        else:
            _, signed_headers, _ = self.oauth_client.sign(
                add_params_to_uri(url, params), http_method=method, headers=headers
            )
            return await self.session.request(method, url, params=params, headers=signed_headers)

    @classmethod
    def register_extension(cls, extension: Type[Extension]):
        extension.register(cls)

    @classmethod
    def unregister_extension(cls, extension: Type[Extension]):
        extension.unregister(cls)

    async def close_connection(self):
        await self.session.close()
resource_owner_key = ''
resource_owner_secret = ''

if client_key == '' or client_secret == '':
    print "Please change your client key and secret in connectXAuth.py header"
    sys.exit(0)

if username == 'USER_NAME' or password == 'USER_PASSWORD':
    print "Please change username and password in connectXAuth.py header"
    sys.exit(0)

client = Client(client_key, client_secret=client_secret, signature_type=SIGNATURE_TYPE_BODY)
headers = {"Content-Type": CONTENT_TYPE_FORM_URLENCODED}
body = 'x_auth_mode=client_auth&x_auth_username='******'&x_auth_password='******'oauth_token')
resource_owner_secret = oauth_tokens.get('oauth_token_secret')

cred = {"client_key": client_key, "client_secret": client_secret,
        "resource_owner_key": resource_owner_key,
        "resource_owner_secret": resource_owner_secret}

import json
with open('credentials.json', 'w') as outfile:
Example #47
0
if client_key == '' or client_secret == '':
    print "Please change your client key and secret in connectXAuth.py header"
    sys.exit(0)

if username == 'USER_NAME' or password == 'USER_PASSWORD':
    print "Please change username and password in connectXAuth.py header"
    sys.exit(0)

client = Client(client_key,
                client_secret=client_secret,
                signature_type=SIGNATURE_TYPE_BODY)
headers = {"Content-Type": CONTENT_TYPE_FORM_URLENCODED}
body = 'x_auth_mode=client_auth&x_auth_username='******'&x_auth_password='******'oauth_token')
resource_owner_secret = oauth_tokens.get('oauth_token_secret')

cred = {
    "client_key": client_key,
    "client_secret": client_secret,
    "resource_owner_key": resource_owner_key,
    "resource_owner_secret": resource_owner_secret
Example #48
0
class BaseEndpointTest(TestCase):

    def setUp(self):
        self.validator = MagicMock(spec=RequestValidator)
        self.validator.allowed_signature_methods = ['HMAC-SHA1']
        self.validator.timestamp_lifetime = 600
        self.endpoint = RequestTokenEndpoint(self.validator)
        self.client = Client('foo', callback_uri='https://c.b/cb')
        self.uri, self.headers, self.body = self.client.sign(
                'https://i.b/request_token')

    def test_ssl_enforcement(self):
        uri, headers, _ = self.client.sign('http://i.b/request_token')
        h, b, s = self.endpoint.create_request_token_response(
                uri, headers=headers)
        self.assertEqual(s, 400)
        self.assertIn('insecure_transport_protocol', b)

    def test_missing_parameters(self):
        h, b, s = self.endpoint.create_request_token_response(self.uri)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_signature_methods(self):
        headers = {}
        headers['Authorization'] = self.headers['Authorization'].replace(
                'HMAC', 'RSA')
        h, b, s = self.endpoint.create_request_token_response(
                self.uri, headers=headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_signature_method', b)

    def test_invalid_version(self):
        headers = {}
        headers['Authorization'] = self.headers['Authorization'].replace(
                '1.0', '2.0')
        h, b, s = self.endpoint.create_request_token_response(
                self.uri, headers=headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_expired_timestamp(self):
        headers = {}
        for pattern in ('12345678901', '4567890123', '123456789K'):
            headers['Authorization'] = sub('timestamp="\d*k?"',
                    'timestamp="%s"' % pattern,
                     self.headers['Authorization'])
            h, b, s = self.endpoint.create_request_token_response(
                    self.uri, headers=headers)
            self.assertEqual(s, 400)
            self.assertIn('invalid_request', b)

    def test_client_key_check(self):
        self.validator.check_client_key.return_value = False
        h, b, s = self.endpoint.create_request_token_response(
                self.uri, headers=self.headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_noncecheck(self):
        self.validator.check_nonce.return_value = False
        h, b, s = self.endpoint.create_request_token_response(
                self.uri, headers=self.headers)
        self.assertEqual(s, 400)
        self.assertIn('invalid_request', b)

    def test_enforce_ssl(self):
        """Ensure SSL is enforced by default."""
        v = RequestValidator()
        e = BaseEndpoint(v)
        c = Client('foo')
        u, h, b = c.sign('http://example.com')
        r = e._create_request(u, 'GET', b, h)
        self.assertRaises(errors.InsecureTransportError,
                e._check_transport_security, r)

    def test_multiple_source_params(self):
        """Check for duplicate params"""
        v = RequestValidator()
        e = BaseEndpoint(v)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                'https://a.b/?oauth_signature_method=HMAC-SHA1',
                'GET', 'oauth_version=foo', URLENCODED)
        headers = {'Authorization': 'OAuth oauth_signature="foo"'}
        headers.update(URLENCODED)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                'https://a.b/?oauth_signature_method=HMAC-SHA1',
                'GET',
                'oauth_version=foo',
                headers)
        headers = {'Authorization': 'OAuth oauth_signature_method="foo"'}
        headers.update(URLENCODED)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                'https://a.b/',
                'GET',
                'oauth_signature=foo',
                headers)

    def test_duplicate_params(self):
        """Ensure params are only supplied once"""
        v = RequestValidator()
        e = BaseEndpoint(v)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                'https://a.b/?oauth_version=a&oauth_version=b',
                'GET', None, URLENCODED)
        self.assertRaises(errors.InvalidRequestError, e._create_request,
                'https://a.b/', 'GET', 'oauth_version=a&oauth_version=b',
                URLENCODED)

    def test_mandated_params(self):
        """Ensure all mandatory params are present."""
        v = RequestValidator()
        e = BaseEndpoint(v)
        r = e._create_request('https://a.b/', 'GET',
                'oauth_signature=a&oauth_consumer_key=b&oauth_nonce',
                URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                e._check_mandatory_parameters, r)

    def test_oauth_version(self):
        """OAuth version must be 1.0 if present."""
        v = RequestValidator()
        e = BaseEndpoint(v)
        r = e._create_request('https://a.b/', 'GET',
                ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
                 'oauth_timestamp=a&oauth_signature_method=RSA-SHA1&'
                 'oauth_version=2.0'),
                URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                e._check_mandatory_parameters, r)

    def test_oauth_timestamp(self):
        """Check for a valid UNIX timestamp."""
        v = RequestValidator()
        e = BaseEndpoint(v)

        # Invalid timestamp length, must be 10
        r = e._create_request('https://a.b/', 'GET',
                ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
                 'oauth_version=1.0&oauth_signature_method=RSA-SHA1&'
                 'oauth_timestamp=123456789'),
                URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                e._check_mandatory_parameters, r)

        # Invalid timestamp age, must be younger than 10 minutes
        r = e._create_request('https://a.b/', 'GET',
                ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
                 'oauth_version=1.0&oauth_signature_method=RSA-SHA1&'
                 'oauth_timestamp=1234567890'),
                URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                e._check_mandatory_parameters, r)

        # Timestamp must be an integer
        r = e._create_request('https://a.b/', 'GET',
                ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
                 'oauth_version=1.0&oauth_signature_method=RSA-SHA1&'
                 'oauth_timestamp=123456789a'),
                URLENCODED)
        self.assertRaises(errors.InvalidRequestError,
                e._check_mandatory_parameters, r)

    def test_signature_method_validation(self):
        """Ensure valid signature method is used."""

        body = ('oauth_signature=a&oauth_consumer_key=b&oauth_nonce=c&'
                'oauth_version=1.0&oauth_signature_method=%s&'
                'oauth_timestamp=1234567890')

        uri = 'https://example.com/'

        class HMACValidator(RequestValidator):

            @property
            def allowed_signature_methods(self):
                return (SIGNATURE_HMAC,)

        v = HMACValidator()
        e = BaseEndpoint(v)
        r = e._create_request(uri, 'GET', body % 'RSA-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'PLAINTEXT', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'shibboleth', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)

        class RSAValidator(RequestValidator):

            @property
            def allowed_signature_methods(self):
                return (SIGNATURE_RSA,)

        v = RSAValidator()
        e = BaseEndpoint(v)
        r = e._create_request(uri, 'GET', body % 'HMAC-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'PLAINTEXT', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'shibboleth', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)

        class PlainValidator(RequestValidator):

            @property
            def allowed_signature_methods(self):
                return (SIGNATURE_PLAINTEXT,)

        v = PlainValidator()
        e = BaseEndpoint(v)
        r = e._create_request(uri, 'GET', body % 'HMAC-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'RSA-SHA1', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)
        r = e._create_request(uri, 'GET', body % 'shibboleth', URLENCODED)
        self.assertRaises(errors.InvalidSignatureMethodError,
                e._check_mandatory_parameters, r)