from __future__ import absolute_import from twisted.web.http_headers import Headers from twisted.internet.error import ConnectionDone, ConnectionLost from twisted.web.client import ResponseDone, ResponseFailed from twisted.web.http import PotentialDataLoss from twisted.internet import defer, protocol import oauth2 import urlparse import urllib import json from weasyl import define defaultSignature = oauth2.SignatureMethod_HMAC_SHA1() defaultTwitterAPI = 'https://api.twitter.com/1.1/' class StringReceiver(protocol.Protocol): def __init__(self, byteLimit=None): self.bytesRemaining = byteLimit self.deferred = defer.Deferred() self._buffer = [] def dataReceived(self, data): data = data[:self.bytesRemaining] self._buffer.append(data) if self.bytesRemaining is not None: self.bytesRemaining -= len(data) if not self.bytesRemaining:
def __init__(self, storage, consumer_key, consumer_secret): self.consumer_key = consumer_key self.consumer_secret = consumer_secret self.storage = storage self._consumer = oauth.Consumer(consumer_key, consumer_secret) self._sigmethod = oauth.SignatureMethod_HMAC_SHA1()
url1 = "https://api.twitter.com/1.1/search/tweets.json" params = { "oauth_version": "1.0", "oauth_nonce": oauth2.generate_nonce(), "oauth_timestamp": int(time.time()) } consumer=oauth2.Consumer(key=" sHxIIacqOzagP0sOWvexVuIEF", secret="MYJ28HJDIF8amIww93CSYPflHJiFgjE1emGLWWCDiBKcvmmj1C") token=oauth2.Token(key=" 159854868-umOhzzDEEODyhLgpxbq3iDjH0vLnPSsCyxJ1arcJ", secret="aT7U4TNzFlrIn7Bd8bLZVkBZsYTa13kWcFWVTNiwLncLy") params["oauth_consumer_key"] = consumer.key # VARIABLE AUTHENCATION PARAMETERS params["oauth_token"] = token.key params["q"] = "Jaipur" req = oauth2.Request(method="GET", url=url1, parameters=params) signature_method = oauth2.SignatureMethod_HMAC_SHA1() req.sign_request(signature_method, consumer, token) url = req.to_url() response = urllib2.Request(url) data = json.load(urllib2.urlopen(response)) filename = params["q"] f = open(filename + "_File.txt", "w") # SAVING DATA TO FILE json.dump(data["statuses"], f) f.close()
def api_request(self, endpoint=None, method='GET', params={}, files=None, replace=False): self.headers.update({'Content-Type': 'application/json'}) self.headers.update({'Content-Length': '0'}) if endpoint is None and files is None: raise FlickrAPIError('Please supply an API endpoint to hit.') qs = { 'format': 'json', 'nojsoncallback': 1, 'method': endpoint, 'api_key': self.api_key } if method == 'POST': if files is not None: # To upload/replace file, we need to create a fake request # to sign parameters that are not multipart before we add # the multipart file to the parameters... # OAuth is not meant to sign multipart post data http_url = self.replace_api_url if replace else self.upload_api_url faux_req = oauth.Request.from_consumer_and_token( self.consumer, token=self.token, http_method="POST", http_url=http_url, parameters=params) faux_req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), self.consumer, self.token) all_upload_params = dict(parse_qsl(faux_req.to_postdata())) # For Tumblr, all media (photos, videos) # are sent with the 'data' parameter all_upload_params['photo'] = (files.name, files.read()) body, content_type = self.encode_multipart_formdata( all_upload_params) self.headers.update({ 'Content-Type': content_type, 'Content-Length': str(len(body)) }) req = urllib2.Request(http_url, body, self.headers) try: req = urllib2.urlopen(req) except urllib2.HTTPError, e: # Making a fake resp var because urllib2.urlopen doesn't # return a tuple like OAuth2 client.request does resp = {'status': e.code} content = e.read() # After requests is finished, delete Content Length & Type so # requests after don't use same Length and take (i.e 20 sec) del self.headers['Content-Type'] del self.headers['Content-Length'] # If no error, assume response was 200 resp = {'status': 200} content = req.read() content = etree.XML(content) stat = content.get('stat') or 'ok' if stat == 'fail': if content.find('.//err') is not None: code = content.findall('.//err[@code]') msg = content.findall('.//err[@msg]') if len(code) > 0: if len(msg) == 0: msg = 'An error occurred making your Flickr API request.' else: msg = msg[0].get('msg') code = int(code[0].get('code')) content = { 'stat': 'fail', 'code': code, 'message': msg } else: photoid = content.find('.//photoid') if photoid is not None: photoid = photoid.text content = {'stat': 'ok', 'photoid': photoid} else: url = self.rest_api_url + '?' + urllib.urlencode( qs) + '&' + urllib.urlencode(params) resp, content = self.client.request(url, 'POST', headers=self.headers)
token = '' token_secret = '' consumer = oauth2.Consumer(consumer_key, consumer_secret) url = 'http://api.yelp.com/v2/search?term=bars&location=sf' print 'URL: %s' % (url,) oauth_request = oauth2.Request('GET', url, {}) oauth_request.update({'oauth_nonce': oauth2.generate_nonce(), 'oauth_timestamp': oauth2.generate_timestamp(), 'oauth_token': token, 'oauth_consumer_key': consumer_key}) token = oauth2.Token(token, token_secret) oauth_request.sign_request(oauth2.SignatureMethod_HMAC_SHA1(), consumer, token) signed_url = oauth_request.to_url() print 'Signed URL: %s' % (signed_url,) conn = urllib2.urlopen(signed_url, None) json_response = conn.read() print json_response yelp_data = json.loads(json_response) print yelp_data
from urlparse import parse_qs import oauth2 as oauth import requests from pyramid.httpexceptions import HTTPFound from pyramid.settings import asbool from velruse.api import AuthenticationComplete from velruse.exceptions import AuthenticationDenied from velruse.exceptions import ThirdPartyFailure REQUEST_URL = 'https://bitbucket.org/api/1.0/oauth/request_token/' ACCESS_URL = 'https://bitbucket.org/api/1.0/oauth/access_token/' USER_URL = 'https://bitbucket.org/api/1.0/user' SIGMETHOD = oauth.SignatureMethod_HMAC_SHA1() class BitbucketAuthenticationComplete(AuthenticationComplete): """Bitbucket auth complete""" provider = 'bitbucket' def includeme(config): config.add_route("bitbucket_login", "/bitbucket/login") config.add_route("bitbucket_process", "/bitbucket/process", use_global_views=True, factory=bitbucket_process) config.add_view(bitbucket_login, route_name="bitbucket_login") settings = config.registry.settings
def test_oauth_workflow(self): request_token_url = 'http://testserver' + reverse( 'api:oauth_request_token') authorize_token_url = 'http://testserver' + reverse( 'api:oauth_user_authorization') # create consumer for tests c = Client() c.login_user('ggbaker') c.logout() consumer = Consumer(name='Test Consumer', description='Consumer to do some tests with', status=ACCEPTED, user=User.objects.get(username='******'), xauth_allowed=False) consumer.generate_random_codes() consumer.save() ci = ConsumerInfo(consumer=consumer) ci.admin_contact = '*****@*****.**' ci.permissions = ['courses', 'grades'] ci.save() # generate request token oauth_request = oauth.Request.from_consumer_and_token( consumer, http_url=request_token_url, parameters={'oauth_callback': 'oob'}) oauth_request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) resp = c.get(request_token_url, **oauth_request.to_header()) self.assertEqual(resp.status_code, 200) request_token = dict( urllib.parse.parse_qsl(resp.content.decode('utf8'))) # get auth verifier c.login_user('ggbaker') resp = c.get(authorize_token_url, {'oauth_token': request_token['oauth_token']}) self.assertEqual(resp.status_code, 200) resp = c.post(authorize_token_url, { 'oauth_token': request_token['oauth_token'], 'authorize_access': 'on' }) self.assertEqual(resp.status_code, 200) parser = etree.HTMLParser() root = etree.fromstring(resp.content, parser=parser) verifier_elt = root.xpath('//*[@id="verifier"]')[0] oauth_verifier = verifier_elt.text.strip() c.logout() # get access token token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret']) token.set_verifier(oauth_verifier) oauth_request = oauth.Request.from_consumer_and_token( consumer, token, http_url=authorize_token_url) oauth_request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, token) resp = c.get(authorize_token_url, **oauth_request.to_header())
def auth_request(endpoint, method, fname="", body=""): """Builds a signed token for making requests to Twitter API. Uses python-oauth2 (https://github.com/joestump/python-oauth2) Args: endpoint (str): Endpoint for Twitter API service. method (str): HTTP action verb. fname (str): Function-specific conditions ("twt_connect" or "twt_auth"). body: (str): For Twitter's verifier code. """ state = gen_csrf_token() # Grab some values for params and oauth consumer_key = (json.loads( open("catalog/login/client_secrets_twt.json", "r").read())["web"]["consumer_key"]) consumer_key_sec = json.loads( open("catalog/login/client_secrets_twt.json", "r").read())["web"]["client_secret"] oauth_token = json.loads( open("catalog/login/client_secrets_twt.json", "r").read())["web"]["access_token"] oauth_token_sec = (json.loads( open("catalog/login/client_secrets_twt.json", "r").read())["web"]["access_token_secret"]) # Parameters required to make an authorized Twitter request params = {} if fname == "connect_twt": params["oauth_callback"] = urllib.quote(url_for("bp_login.auth_twt")) if fname == "disconnect_twt": params["access_token"] = login_session["access_token"] params["oauth_consumer_key"] = consumer_key params["oauth_nonce"] = base64.b64encode(state) params["oauth_timestamp"] = str(int(time.time())) params["oauth_token"] = oauth_token params["oauth_version"] = "1.0" # Create our request, token and consumer objects. req = oauth.Request(method="POST", url=endpoint, parameters=params) token = oauth.Token(key=oauth_token, secret=oauth_token_sec) consumer = oauth.Consumer(key=consumer_key, secret=consumer_key_sec) # Sign the request to get oauth_signature and oauth_signature parameters # Using oauth simplifies the cumbersome process of creating a signature # https://dev.twitter.com/oauth/overview/creating-signatures signature_method = oauth.SignatureMethod_HMAC_SHA1() req.sign_request(signature_method, consumer, token) # Get the key values from the request object and sort them # OAuth spec says to sort lexigraphically # The first item is not specified in the Twitter docs, # so we exclude it req_keys = sorted(req.keys()[1:]) # Build the required Authorization header value # https://dev.twitter.com/oauth/overview/authorizing-requests auth_header = "OAuth " for k in req_keys: val = urllib.quote(req[k]) k = urllib.quote(k) auth_header += k auth_header += '="' auth_header += val auth_header += '"' if k == "oauth_version": break else: auth_header += ", " # Need to encode the header data header = urllib.urlencode({"Authorization": auth_header}) client = oauth.Client(consumer, token) data = client.request(endpoint, method=method, body=body, headers=header)[1] return data
def handle(self, *args, **options): project = options.get('project') host = options.get('host') file = options.get('file') consumer_key = options.get('consumer_key') consumer_secret = options.get('consumer_secret') debug = options.get('debug') if not project: self.stdout.write( "You must supply a project name to POST data to: " "--project project\n") return if not host: self.stdout.write( "You must supply a host name to POST data to: " "--host host\n") return if not os.path.isfile(file): self.stdout.write( "You must supply a JSON file to POST: --file JSON file\n") return if not consumer_key: self.stdout.write( "You must supply the projects consumer key to POST: " "--key key or settings.OAUTH_CONSUMER_KEY\n") return if not consumer_secret: self.stdout.write( "You must supply the projects consumer secret to POST: " "--key key or settings.OAUTH_CONSUMER_SECRET\n") return ##Open the json file## json_data = "" with open(file) as f: json_data = f.read() path = '/%s/api/load_test' % (project) uri = 'https://%s%s' % (host, path) params = { 'oauth_version': "1.0", 'oauth_nonce': oauth.generate_nonce(), 'oauth_timestamp': int(time.time()), 'user': project, 'data': urllib.quote(json_data) } #There is no requirement for the token in two-legged #OAuth but we still need the token object. token = oauth.Token(key="", secret="") consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret) params['oauth_token'] = token.key params['oauth_consumer_key'] = consumer.key req = oauth.Request(method="POST", url=uri, parameters=params) #Set the signature signature_method = oauth.SignatureMethod_HMAC_SHA1() #Sign the request req.sign_request(signature_method, consumer, token) #Build the header header = req.to_header() header['Content-type'] = 'application/x-www-form-urlencoded' header['Accept'] = 'text/plain' if debug: self.stdout.write(str(header) + "\n") self.stdout.write(req.to_postdata() + "\n") else: conn = httplib.HTTPSConnection(host) conn.request("POST", path, req.to_postdata(), header) response = conn.getresponse() self.stdout.write( "status:%s\nreason:%s\nresponse:%s\n" % (response.status, response.reason, response.read()))
REPOSITORIES_URL = "https://localhost/pulp/api/v2/repositories/" # Setup a standard HTTPSConnection object connection = httplib.HTTPSConnection("localhost", "443") # Create an OAuth Consumer object consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET) # Test 1 print "\n --- Test1 ---" # Formulate a OAuth request with the embedded consumer with key/secret pair oauth_request = oauth.Request.from_consumer_and_token(consumer, http_method="GET", http_url=CONSUMER_URL) # Sign the Request. This applies the HMAC-SHA1 hash algorithm oauth_request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) # Add the pulp-user header variable headers = dict(oauth_request.to_header().items() + {'pulp-user': '******'}.items()) print "\nHEADERS : %s", headers # Actually make the request connection.request("GET", "/pulp/api/v2/consumers/test-consumer/", headers=headers) # Get the response and read the output response = connection.getresponse() output = response.read() print "\nRESPONSE : %s", output
def __init__(self, consumer_key, consumer_secret, token, token_secret): token = oauth.Token(token, token_secret) self._Consumer = oauth.Consumer(consumer_key, consumer_secret) self._signature_method = oauth.SignatureMethod_HMAC_SHA1() self._access_token = token
class FitbitOauthClient(oauth.Client): API_ENDPOINT = "https://api.fitbit.com" AUTHORIZE_ENDPOINT = "https://www.fitbit.com" API_VERSION = 1 _signature_method = oauth.SignatureMethod_HMAC_SHA1() request_token_url = "%s/oauth/request_token" % API_ENDPOINT access_token_url = "%s/oauth/access_token" % API_ENDPOINT authorization_url = "%s/oauth/authorize" % AUTHORIZE_ENDPOINT def __init__(self, consumer_key, consumer_secret, user_key=None, user_secret=None, user_id=None, *args, **kwargs): if user_key and user_secret: self._token = oauth.Token(user_key, user_secret) else: # This allows public calls to be made self._token = None if user_id: self.user_id = user_id self._consumer = FitbitConsumer(consumer_key, consumer_secret) super(FitbitOauthClient, self).__init__(self._consumer, *args, **kwargs) def _request(self, method, url, **kwargs): """ A simple wrapper around requests. """ return requests.request(method, url, **kwargs) def make_request(self, url, data={}, method=None, **kwargs): """ Builds and makes the Oauth Request, catches errors https://wiki.fitbit.com/display/API/API+Response+Format+And+Errors """ if not method: method = 'POST' if data else 'GET' headers = kwargs.pop('headers', {}) request = oauth.Request.from_consumer_and_token(self._consumer, self._token, http_method=method, http_url=url, parameters=data) request.sign_request(self._signature_method, self._consumer, self._token) headers.update(request.to_header()) response = self._request(method, url, data=data, headers=headers) if response.status_code == 401: raise HTTPUnauthorized(response) elif response.status_code == 403: raise HTTPForbidden(response) elif response.status_code == 404: raise HTTPNotFound(response) elif response.status_code == 409: raise HTTPConflict(response) elif response.status_code >= 500: raise HTTPServerError(response) elif response.status_code >= 400: raise HTTPBadRequest(response) return response def fetch_request_token(self, parameters=None): """ Step 1 of getting authorized to access a user's data at fitbit: this makes a signed request to fitbit to get a token to use in the next step. Returns that token. Set parameters['oauth_callback'] to a URL and when the user has granted us access at the fitbit site, fitbit will redirect them to the URL you passed. This is how we get back the magic verifier string from fitbit if we're a web app. If we don't pass it, then fitbit will just display the verifier string for the user to copy and we'll have to ask them to paste it for us and read it that way. """ """ via headers -> OAuthToken Providing 'oauth_callback' parameter in the Authorization header of request_token_url request, will have priority over the dev.fitbit.com settings, ie. parameters = {'oauth_callback': 'callback_url'} """ request = oauth.Request.from_consumer_and_token( self._consumer, http_url=self.request_token_url, parameters=parameters) request.sign_request(self._signature_method, self._consumer, None) response = self._request(request.method, self.request_token_url, headers=request.to_header()) return oauth.Token.from_string(response.content) def authorize_token_url(self, token): """Step 2: Given the token returned by fetch_request_token(), return the URL the user needs to go to in order to grant us authorization to look at their data. Then redirect the user to that URL, open their browser to it, or tell them to copy the URL into their browser. """ request = oauth.Request.from_token_and_callback( token=token, http_url=self.authorization_url) return request.to_url() #def authorize_token(self, token): # # via url # # -> typically just some okay response # request = oauth.Request.from_token_and_callback(token=token, # http_url=self.authorization_url) # response = self._request(request.method, request.to_url(), # headers=request.to_header()) # return response.content def fetch_access_token(self, token, verifier): """Step 4: Given the token from step 1, and the verifier from step 3 (see step 2), calls fitbit again and returns an access token object. Extract .key and .secret from that and save them, then pass them as user_key and user_secret in future API calls to fitbit to get this user's data. """ client = OAuth1Session(self._consumer.key, client_secret=self._consumer.secret, resource_owner_key=token.key, resource_owner_secret=token.secret, verifier=verifier) response = client.fetch_access_token(self.access_token_url) self.user_id = response['encoded_user_id'] self._token = oauth.Token(key=response['oauth_token'], secret=response['oauth_token_secret']) return self._token
def server(self): result = oauth.Server() result.add_signature_method(oauth.SignatureMethod_PLAINTEXT()) result.add_signature_method(oauth.SignatureMethod_HMAC_SHA1()) return result
def __init__(self, api_key, shared_secret, httplib2_inst=None): """Override init to ensure required args""" super(TwoLegged, self).__init__(api_key, shared_secret, httplib2_inst) self.endpoint = PRIVATE_ENDPOINT self.hmac_sha1_signature = oauth.SignatureMethod_HMAC_SHA1() self.plaintext_signature = oauth.SignatureMethod_PLAINTEXT()
class OAuthResource(resource.Resource): """ Represents a 2-legged OAuth 1.0 protected Resource. When using 2-legged OAuth, you do not need to provide an OAuth access token to access a resource. Each request must be properly signed using the `HMAC-SHA1` signature method. See the OAuth 1.0 Protocol spec: http://tools.ietf.org/html/rfc5849 """ oauth_server = oauth2.Server( signature_methods={'HMAC-SHA1': oauth2.SignatureMethod_HMAC_SHA1()}) def __init__(self, secret_store): resource.Resource.__init__(self) self.secret_store = secret_store def _validate_request(self, request): """ Validates a 2-legged OAuth 1.0 twisted.web.http.Request object. Parameters are accepeted as GET/POST arguments, or in the Authorization header. """ url = str(request.URLPath()) headers = dict(request.requestHeaders.getAllRawHeaders()) args = {} for key, values in request.args.iteritems(): if len(values) > 1: # error: argument keys cannot be repeated! raise KeyError('request argument %s cannot be repeated' % key) args[key] = values[0] oauth_request = oauth2.Request.from_request(request.method, url, headers=headers, parameters=args) key = args['oauth_consumer_key'] secret = self.secret_store.get_secret(key) if secret is None: raise oauth2.Error('Invalid Consumer Key') consumer = oauth2.Consumer(key=key, secret=secret) self.oauth_server.verify_request(oauth_request, consumer, None) def _oauth_protect(render_method): """Decorates this Resource's render method to protect against unauthorized access.""" @wraps(render_method) def wrapper(self, request): try: self._validate_request(request) return render_method(self, request) except (oauth2.MissingSignature, ValueError, KeyError): status = http.BAD_REQUEST return _JSON_response(request, status, {'error': 'bad_request'}) except oauth2.Error: status = http.UNAUTHORIZED return _JSON_response(request, status, {'error': 'unauthorized'}) except: log.err() status = http.INTERNAL_SERVER_ERROR return _JSON_response(request, status, {'error': 'internal_server_error'}) return wrapper @_oauth_protect def render(self, request): """Render code used from http://twistedmatrix.com/trac/browser/tags/releases/twisted-11.0.0/twisted/web/resource.py """ m = getattr(self, 'render_' + request.method, None) if not m: allowedMethods = (getattr(self, 'allowedMethods', 0) or resource._computeAllowedMethods(self)) status = http.NOT_ALLOWED description = 'Unsupported method. Allowed methods: %s' \ % str(allowedMethods) json = { 'error': 'method_not_allowed', 'error_description': description } request.setHeader('Allow', ', '.join(allowedMethods)) return _JSON_response(request, status, json) return m(request)
def get_user_api(users,APIUrl,pool_oauth,globalCounter): size_deleted=0 unreachable_user=[] active_users=[] user_id="" tweet_counter=0 pool_ind=0 for user in users:#.skip(245001): #last count79447 #concatinate 100 ids in a string format with a 54563999e0d4c11d225f3d9f"," in between them then provide it to the API globalCounter+=1 user_id=str(int(user)) #print idstr tweet_counter +=1 print "Calling API on user lookup...", tweet_counter url = APIUrl try: params = {"oauth_version":"1.0","oauth_nonce": oauth2.generate_nonce(),"oauth_timestamp":int(time.time())} params["oauth_consumer_key"] = (pool_oauth[pool_ind][0]).key params["oauth_token"] = (pool_oauth[pool_ind][1]).key params["user_id"] =user_id #list of 100 tweets #params["include_entities"] ="" #optional #params["trim_user"] =""#optional #params["map"] = ""#optional req = oauth2.Request(method="GET", url=url, parameters=params) signature_method = oauth2.SignatureMethod_HMAC_SHA1()# HMAC, twitter use sha-1 160 bit encryption req.sign_request(signature_method, (pool_oauth[pool_ind][0]), (pool_oauth[pool_ind][1])) headers = req.to_header() url = req.to_url() response = urllib2.Request(url) data = json.load(urllib2.urlopen(response))#format results as json if len(data[0])>0: saveToDB(data[0]) active_users.append(user_id) else: print "this user is unreachable", user_id unreachable_user.append(user_id) unreachable.write(str(user_id)+'\n') print data print "size of unreachable_user: "******"input size",len(input_ids) #print "output size",len(output_ids) #print deleted_ids user_id="" #print "global counter:", globalCounter except Exception, ex: print 'Exception: '+str(ex) print "this user is unreachable", user_id unreachable_user.append(user_id) unreachable.write(str(user_id)+'\n') finally:
class Client: """A base class to authenticate and work with Marketplace OAuth. """ signature_method = oauth.SignatureMethod_HMAC_SHA1() def __init__(self, domain=MARKETPLACE_DOMAIN, protocol=MARKETPLACE_PROTOCOL, port=MARKETPLACE_PORT, prefix='', consumer_key=None, consumer_secret=None): self.domain = domain self.protocol = protocol self.port = port self.prefix = prefix self.conn = None if consumer_secret and consumer_key: self.conn = self.get_connection(consumer_key, consumer_secret) @staticmethod def get_connection(consumer_key, consumer_secret): """Provide Connection object used for communication with the API """ return Connection(consumer_key, consumer_secret) def url(self, key): """Creates a full URL to the API using urls dict """ return urlunparse((self.protocol, '%s:%s' % (self.domain, self.port), '%s/api%s' % (self.prefix, URLS[key]), '', '', '')) def validate_manifest(self, manifest_url): """Order manifest validation :returns: dict with an ``id`` to check the result """ # there is a bug request to make this synchronous on Marketplace side # this will return the same as :method:`get_manifest_validation_result` return self.conn.fetch('POST', self.url('validate'), {'manifest': manifest_url}) def get_manifest_validation_result(self, manifest_id): """Check if the manifest is processed and if it's valid :param: manifest_id (string) id received in :method:`validate_manifest` :returns: (HttpResponse) * status_code - 200 if manifest in validation * content - (dict) with some important fields alongs the other: * processed (Boolean) has manifest been processed? * valid (Boolean) is manifest valid? * validation - empty string if valid else error dict """ return self.conn.fetch('GET', self.url('validation_result') % manifest_id) def is_manifest_valid(self, manifest_id): """Check validation shortcut :param: manifest_id (string) id received in :method:`validate_manifest` :returns: * True if manifest was valid * None if manifest wasn't checked yet * validation dict if not valid """ response = self.get_manifest_validation_result(manifest_id) if response.status_code != 200: raise Exception(response.status_code) content = json.loads(response.content) if not content['processed']: return None if content['valid']: return True return content['validation'] def create(self, manifest_id): """Issue create process :returns: HttpResponse: * status_code - 201 if successful * content - dict with some important fields: * id (string) application id in marketplace * resource_uri (string) url in marketplace * slug (string) unique name in marketplace """ return self.conn.fetch('POST', self.url('create'), {'manifest': '%s' % manifest_id}) def list_webapps(self): """Lists all webapps owned by user :returns: list """ response = self.conn.fetch('GET', self.url('create')) return response def update(self, app_id, data): """Update app identified by app_id with data :params: * app_id (int) id in the marketplace received with :method:`create` * data (dict) some keys are required: * *name*: the title of the app. Maximum length 127 characters. * *summary*: the summary of the app. Maximum length 255 characters. * *categories*: a list of the categories, at least two of the category ids provided from the category api (see below). * *support_email*: the email address for support. * *device_types*: a list of the device types at least one of: 'desktop', 'phone', 'tablet'. * *payment_type*: only choice at this time is 'free'. :returns: HttResponse: * status_code (int) 202 if successful * content (dict) or empty if successful """ assert ('name' in data and data['name'] and 'summary' in data and 'categories' in data and data['categories'] and 'support_email' in data and data['support_email'] and 'device_types' in data and data['device_types'] and 'payment_type' in data and data['payment_type'] and 'privacy_policy' in data and data['privacy_policy']) return self.conn.fetch('PUT', self.url('app') % app_id, data) def status(self, app_id): """View details of an app identified by its id :returns: HttResponse: * status_code (int) 200 if successful * content (JSON String) with all available app information """ return self.conn.fetch('GET', self.url('app') % app_id) def delete(self, app_id): """Delete an app from Marketplace """ # XXX: This isn't yet implemented on API # return self.conn.fetch('DELETE', self.url('app') % app_id) raise NotImplementedError() def create_screenshot(self, app_id, filename, position=1): """Add a screenshot to the web app identified by by ``app_id``. Screenshots are ordered by ``position``. :returns: HttpResponse: * status_code (int) 201 is successful * content (dict) containing screenshot data """ # prepare file for upload with open(filename, 'rb') as s_file: s_content = s_file.read() s_encoded = b64encode(s_content) url = self.url('create_screenshot') % app_id mtype, encoding = mimetypes.guess_type(filename) if mtype is None: mtype = 'image/jpeg' data = {'position': position, 'file': {'type': mtype, 'data': s_encoded}} return self.conn.fetch('POST', url, data) def get_screenshot(self, screenshot_id): """Get information about screenshot or video :returns HttpResponse: * status_code (int) 200 is successful * content (JSON string) """ return self.conn.fetch('GET', self.url('screenshot') % screenshot_id) def del_screenshot(self, screenshot_id): """Deletes screenshot :returns: HttpResponse: * status_code (int) 204 if successful """ return self.conn.fetch('DELETE', self.url('screenshot') % screenshot_id) def get_categories(self): """Get all categories from Marketplae """ return self.conn.fetch('GET', self.url('categories')) def app_state(self, app_id, status=None, disabled_by_user=None): """Once all the data has been completed and at least one screenshot created, you can push the app to the review queue status (optional): key statuses are incomplete: incomplete pending: pending public: public waiting: waiting to be public disabled_by_user (optional): True or False Valid transitions that users can initiate are: waiting to be public to public: occurs when the app has been reviewed, but not yet been made public. incomplete to pending: call this once your app has been completed and it will be added to the Marketplace review queue. This can only be called if all the required data is there. If not, you'll get an error containing the reason disabled_by_user: by changing this value from True to False you can enable or disable an app """ assert status is not None or disabled_by_user is not None data = {} if status: data['status'] = status if disabled_by_user: data['disabled_by_user'] = disabled_by_user return self.conn.fetch('PATCH', self.url('enable') % app_id, data)
class OAuthClient(Client): """OauthClient can make magically signed requests.""" signature_method = oauth.SignatureMethod_HMAC_SHA1() def get(self, url, consumer=None, token=None, callback=False, verifier=None, params=None): url = get_absolute_url(url) if params: url = '%s?%s' % (url, urllib.urlencode(params)) req = oauth.Request(method='GET', url=url, parameters=_get_args(consumer, callback=callback, verifier=verifier)) req.sign_request(self.signature_method, consumer, token) return super(OAuthClient, self).get(req.to_url(), HTTP_HOST='api', HTTP_AUTHORIZATION='OAuth realm=""', **req) def delete(self, url, consumer=None, token=None, callback=False, verifier=None): url = get_absolute_url(url) req = oauth.Request(method='DELETE', url=url, parameters=_get_args(consumer, callback=callback, verifier=verifier)) req.sign_request(self.signature_method, consumer, token) return super(OAuthClient, self).delete(req.to_url(), HTTP_HOST='api', HTTP_AUTHORIZATION='OAuth realm=""', **req) def post(self, url, consumer=None, token=None, callback=False, verifier=None, data={}): url = get_absolute_url(url) params = _get_args(consumer, callback=callback, verifier=verifier) params.update(data_keys(data)) req = oauth.Request(method='POST', url=url, parameters=params) req.sign_request(self.signature_method, consumer, token) return super(OAuthClient, self).post(req.to_url(), HTTP_HOST='api', HTTP_AUTHORIZATION='OAuth realm=""', data=data, headers=req.to_header()) def put(self, url, consumer=None, token=None, callback=False, verifier=None, data={}, content_type=MULTIPART_CONTENT, **kwargs): """ Send a resource to the server using PUT. """ # If data has come from JSON remove unicode keys. data = dict([(str(k), v) for k, v in data.items()]) url = get_absolute_url(url) params = _get_args(consumer, callback=callback, verifier=verifier) params.update(data_keys(data)) req = oauth.Request(method='PUT', url=url, parameters=params) req.sign_request(self.signature_method, consumer, token) post_data = encode_multipart(BOUNDARY, data) parsed = urlparse.urlparse(url) query_string = urllib.urlencode(req, doseq=True) r = { 'CONTENT_LENGTH': len(post_data), 'CONTENT_TYPE': content_type, 'PATH_INFO': urllib.unquote(parsed[2]), 'QUERY_STRING': query_string, 'REQUEST_METHOD': 'PUT', 'wsgi.input': FakePayload(post_data), 'HTTP_HOST': 'api', 'HTTP_AUTHORIZATION': 'OAuth realm=""', } r.update(req) response = self.request(**r) return response
def __init__(self): self.signature_method = oauth.SignatureMethod_HMAC_SHA1() self.consumer = oauth.Consumer(self.key, self.secret)
def authorize(self, http): """Authorize an httplib2.Http instance with these Credentials Args: http - An instance of httplib2.Http or something that acts like it. Returns: A modified instance of http that was passed in. Example: h = httplib2.Http() h = credentials.authorize(h) You can't create a new OAuth subclass of httplib2.Authenication because it never gets passed the absolute URI, which is needed for signing. So instead we have to overload 'request' with a closure that adds in the Authorization header and then calls the original version of 'request()'. """ request_orig = http.request signer = oauth.SignatureMethod_HMAC_SHA1() # The closure that will replace 'httplib2.Http.request'. def new_request(uri, method='GET', body=None, headers=None, redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None): """Modify the request headers to add the appropriate Authorization header.""" response_code = 302 http.follow_redirects = False while response_code in [301, 302]: req = oauth.Request.from_consumer_and_token(self.consumer, self.token, http_method=method, http_url=uri) req.sign_request(signer, self.consumer, self.token) if headers is None: headers = {} headers.update(req.to_header()) if 'user-agent' in headers: headers['user-agent'] = self.user_agent + ' ' + headers[ 'user-agent'] else: headers['user-agent'] = self.user_agent resp, content = request_orig(uri, method, body, headers, redirections, connection_type) response_code = resp.status if response_code in [301, 302]: uri = resp['location'] # Update the stored credential if it becomes invalid. if response_code == 401: logging.info('Access token no longer valid: %s' % content) self._invalid = True if self.store is not None: self.store(self) raise CredentialsInvalidError( "Credentials are no longer valid.") return resp, content http.request = new_request return http
def main(key,secret,url): sig = oauth.SignatureMethod_HMAC_SHA1() auth_url = 'authenticate/' purge_url = 'all_data/' entity_url = 'entity/' comment_url= 'comment/' share_url='share/' like_url='like/' view_url='view/' udid = '1234566788' auth_url = url+auth_url print auth_url ## AUTHENTICATION ## consumer = oauth.Consumer( key, secret) client = oauth.Client( consumer) payload = simplejson.dumps({ 'payload': { 'udid': udid}}) auth_resp = client.request(auth_url ,'POST', body='payload='+simplejson.dumps({'udid':udid})) auth_cont = simplejson.loads(auth_resp[1]) oauth_secret= auth_cont['oauth_token_secret'] oauth_token= auth_cont['oauth_token'] token = oauth.Token(oauth_token,oauth_secret) ## Create client with oauth token client=oauth.Client(consumer,token) print '#'*20 print '## PURGE ALL DATA' print '#'*20 ## PURGE ALL DATA ## req_url = url + purge_url make_request(client, req_url,method='DELETE', data={}, outfile=None) print '#'*20 print '## REMOVE json files ##' print '#'*20 remove('comments.json') remove('shares.json') remove('likes.json') remove('views.json') remove('entities.json') remove('entityA.json') remove('entityB.json') remove('entityC.json') remove('commentsA.json') remove('commentsB.json') remove('commentsC.json') ## Create Entity print '#'*20 print '## CREATE ENTITY ##' print '#'*20 entities = [ {'key':'http://entity1.com','name':'First Entity'}, {'key':'http://entity2.com','name':'Second Entity'} ] req_url = url+entity_url make_request(client, req_url,method='POST', data=entities, outfile='entities.json') print '#'*20 print '## CREATE COMMENT ##' print '#'*20 comments = [ gen_comment('http://entity1.com', i) for i in range(30)] req_url = url+comment_url make_request(client, req_url,method='POST', data=comments, outfile='comments.json') print '#'*20 print '## CREATE LIKES ##' print '#'*20 likes = [ gen_like_and_view('http://entity1.com') , gen_like_and_view('http://entity2.com')] req_url = url+like_url make_request(client, req_url,method='POST', data=likes, outfile='likes.json') ## Not create 3 entities for the purposes of testing entity sorting print '#'*20 print '## CREATE ADDITIONAL ENTITIES ##' print '#'*20 entityA = [ {'key':'http://entityA.com','name':'A Entity'} ] entityB = [ {'key':'http://entityB.com','name':'B Entity'} ] entityC = [ {'key':'http://entityC.com','name':'C Entity'} ] # Sleep between to guarantee creation order req_url = url+entity_url make_request(client, req_url,method='POST', data=entityA, outfile='entityA.json') time.sleep(1) make_request(client, req_url,method='POST', data=entityB, outfile='entityB.json') time.sleep(1) make_request(client, req_url,method='POST', data=entityC, outfile='entityC.json') req_url = url+comment_url comments = [ gen_comment('http://entityA.com', i) for i in range(9)] make_request(client, req_url,method='POST', data=comments, outfile='commentsA.json') comments = [ gen_comment('http://entityB.com', i) for i in range(6)] make_request(client, req_url,method='POST', data=comments, outfile='commentsB.json') comments = [ gen_comment('http://entityC.com', i) for i in range(3)] make_request(client, req_url,method='POST', data=comments, outfile='commentsC.json') ## Create Share for both entities print '#'*20 print '## CREATE SHARES ##' print '#'*20 shares = [ gen_share('http://entity1.com',1) , gen_share('http://entity2.com',2)] req_url = url+share_url make_request(client, req_url,method='POST', data=shares, outfile='shares.json') print '#'*20 print '## CREATE VIEWS ##' print '#'*20 views = [ gen_like_and_view('http://entity1.com') , gen_like_and_view('http://entity2.com')] req_url = url+view_url make_request(client, req_url,method='POST', data=views, outfile='views.json')
def authorize(self, http): """Authorize an httplib2.Http instance with these Credentials Args: http - An instance of httplib2.Http or something that acts like it. Returns: A modified instance of http that was passed in. Example: h = httplib2.Http() h = credentials.authorize(h) You can't create a new OAuth subclass of httplib2.Authenication because it never gets passed the absolute URI, which is needed for signing. So instead we have to overload 'request' with a closure that adds in the Authorization header and then calls the original version of 'request()'. """ request_orig = http.request signer = oauth.SignatureMethod_HMAC_SHA1() # The closure that will replace 'httplib2.Http.request'. def new_request(uri, method='GET', body=None, headers=None, redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None): """Modify the request headers to add the appropriate Authorization header.""" response_code = 302 http.follow_redirects = False while response_code in [301, 302]: # add in xoauth_requestor_id=self._requestor to the uri if self._requestor is None: raise MissingParameter( 'Requestor must be set before using TwoLeggedOAuthCredentials' ) parsed = list(urlparse.urlparse(uri)) q = parse_qsl(parsed[4]) q.append(('xoauth_requestor_id', self._requestor)) parsed[4] = urllib.urlencode(q) uri = urlparse.urlunparse(parsed) req = oauth.Request.from_consumer_and_token(self.consumer, None, http_method=method, http_url=uri) req.sign_request(signer, self.consumer, None) if headers is None: headers = {} headers.update(req.to_header()) if 'user-agent' in headers: headers['user-agent'] = self.user_agent + ' ' + headers[ 'user-agent'] else: headers['user-agent'] = self.user_agent resp, content = request_orig(uri, method, body, headers, redirections, connection_type) response_code = resp.status if response_code in [301, 302]: uri = resp['location'] if response_code == 401: logging.info('Access token no longer valid: %s' % content) # Do not store the invalid state of the Credentials because # being 2LO they could be reinstated in the future. raise CredentialsInvalidError("Credentials are invalid.") return resp, content http.request = new_request return http
#!/usr/bin/env python import oauth2 as oauth import json, urllib, urlparse, unirest, datetime from sentsql.database import Base, db_session, engine from sentsql.model import Concept, Bookmark from sqlalchemy.exc import OperationalError, IntegrityError from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound creds = json.load(open('../configuration.json')) access_token_url = 'https://www.instapaper.com/api/1/oauth/access_token' consumer = oauth.Consumer(creds['instapaper_consumer_key'], creds['instapaper_consumer_secret']) client = oauth.Client(consumer) client.set_signature_method(oauth.SignatureMethod_HMAC_SHA1()) params = {} params["x_auth_username"] = creds['instapaper_username'] params["x_auth_password"] = creds['instapaper_password'] params["x_auth_mode"] = 'client_auth' response, token = client.request(access_token_url, method='POST', body=urllib.urlencode(params)) request_token = dict(urlparse.parse_qsl(token)) token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret']) http = oauth.Client(consumer, token) response, data = http.request('https://www.instapaper.com/api/1/bookmarks/list', method='POST', body=urllib.urlencode({ 'limit': '100' }))
'oauth_signature_method': "HMAC-SHA1", 'oauth_version': "1.0", 'oauth_callback': "http://www.jennywawrzynczak.wordpress.com" } print keys.apikey print keys.apisecret # Setup the Consumer with the api_keys given by the provider consumer = oauth.Consumer(key=keys.apikey, secret=keys.apisecret) # Create our request. Change method, etc. accordingly. req = oauth.Request(method="GET", url=url, parameters=params) print req # Create the signature signature = oauth.SignatureMethod_HMAC_SHA1().sign(req, consumer, None) # Add the Signature to the request req['oauth_signature'] = signature # Make the request to get the oauth_token and the oauth_token_secret # I had to directly use the httplib2 here, instead of the oauth library. print req.to_url() h = httplib2.Http(".cache") resp, content = h.request(req.to_url(), "GET") #parse the content request_token = dict(urlparse.parse_qsl(content)) print "Request Token:"
class BaseHandler(webapp.RequestHandler): def initialize(self, request, response): webapp.RequestHandler.initialize(self, request, response) lang = request.get('lang') if lang: translation.activate(lang) return #main.pyでDBに保存された言語設定をクッキーに入れている。それを取得。Ajaxリクエスト時に使用 lang = Cookies(self).get('lang') if not lang: #なければリクエストヘッダーから取得する self.request.COOKIES = Cookies(self) self.request.META = os.environ lang = translation.get_language_from_request(self.request) translation.activate(lang) self.is_ajax = self.request.headers.get( "X-Requested-With") == "XMLHttpRequest" self.is_mobile = False # if not self.is_ajax: # mobile_useragents = r'iPhone|iPod|Android|dream|CUPCAKE|BlackBerry|webOS|incognito|webmate' # user_agent = self.request.headers["user-agent"] # self.is_mobile = re.search(mobile_useragents, user_agent) is not None def handle_exception(self, exception, debug_mode): if isinstance(exception, NotLoginError): if self.is_ajax: self.error(403) return self.response.out.write("notlogin") # self.request.COOKIES = Cookies(self) self.request.META = os.environ lang = translation.get_language_from_request(self.request) if self.is_mobile: view = '../view/m_index.html' elif lang == "ja": view = '../view/index.html' else: view = '../view/index-en.html' template_values = { 'version': controller.version, 'production': not controller.is_dev } tmpl = os.path.join(os.path.dirname(__file__), view) return self.response.out.write( template.render(tmpl, template_values)) logging.exception(exception) self.error(500) if self.is_ajax: return self.response.out.write("error") tmpl = os.path.join(os.path.dirname(__file__), '../view/500.html') return self.response.out.write(template.render(tmpl, {})) def check_login(self): # if self.check_2lo_oauth(): # return self.session = Session(self.request, self.response) if not self.session.is_login(): raise NotLoginError() def check_2lo_oauth(self): auth_header = self.request.headers.get("Authorization") if not auth_header: return False self.is_ajax = True user_id = self.request.get('xoauth_requestor_id') if not user_id: raise NotLoginError() try: # Builder our request object. request = oauth2.Request.from_request(self.request.method, self.request.path_url, self.request.headers, None, self.request.query) except Exception, e: logging.warn("Could not parse request from method = %s," "uri = %s, headers = %s, query = %s, exception = %s" % (self.request.method, self.request.path_url, self.request.headers, self.request.query, e)) raise NotLoginError() # Fetch the token from Cassandra and build our Consumer object. if request is None or 'oauth_consumer_key' not in request: logging.warn("Request is missing oauth_consumer_key.") raise NotLoginError() try: # Verify the two-legged request. server = oauth2.Server() server.add_signature_method(oauth2.SignatureMethod_HMAC_SHA1()) server.verify_request(request, _get_consumer(request["oauth_consumer_key"]), None) except Exception, e: logging.warn("Could not verify signature (%s)." % e) raise NotLoginError()
def request(self, method, url, body): """ Make the request against the Pulp server, returning a tuple of (status_code, respose_body). This method creates a new connection each time since HTTPSConnection has problems reusing a connection for multiple calls (as claimed by a prior comment in this module). :param method: The HTTP method to be used for the request (GET, POST, etc.) :type method: str :param url: The Pulp URL to make the request against :type url: str :param body: The body to pass with the request :type body: str :return: A 2-tuple of the status_code and response_body. status_code is the HTTP status code (200, 404, etc.). If the server's response is valid json, it will be parsed and response_body will be a dictionary. If not, it will be returned as a string. :rtype: tuple """ headers = dict(self.pulp_connection.headers ) # copy so we don't affect the calling method # Despite the confusing name, 'sslv23' configures m2crypto to use any available protocol in # the underlying openssl implementation. ssl_context = SSL.Context('sslv23') # This restricts the protocols we are willing to do by configuring m2 not to do SSLv2.0 or # SSLv3.0. EL 5 does not have support for TLS > v1.0, so we have to leave support for # TLSv1.0 enabled. ssl_context.set_options(m2.SSL_OP_NO_SSLv2 | m2.SSL_OP_NO_SSLv3) if self.pulp_connection.verify_ssl: ssl_context.set_verify(SSL.verify_peer, depth=100) # We need to stat the ca_path to see if it exists (error if it doesn't), and if so # whether it is a file or a directory. m2crypto has different directives depending on # which type it is. if os.path.isfile(self.pulp_connection.ca_path): ssl_context.load_verify_locations( cafile=self.pulp_connection.ca_path) elif os.path.isdir(self.pulp_connection.ca_path): ssl_context.load_verify_locations( capath=self.pulp_connection.ca_path) else: # If it's not a file and it's not a directory, it's not a valid setting raise exceptions.MissingCAPathException( self.pulp_connection.ca_path) ssl_context.set_session_timeout(self.pulp_connection.timeout) if self.pulp_connection.username and self.pulp_connection.password: raw = ':'.join( (self.pulp_connection.username, self.pulp_connection.password)) encoded = base64.b64encode(raw) headers['Authorization'] = 'Basic ' + encoded elif self.pulp_connection.cert_filename: ssl_context.load_cert(self.pulp_connection.cert_filename) # oauth configuration. This block is only True if oauth is not None, so it won't run on RHEL # 5. if self.pulp_connection.oauth_key and self.pulp_connection.oauth_secret and oauth: oauth_consumer = oauth.Consumer(self.pulp_connection.oauth_key, self.pulp_connection.oauth_secret) oauth_request = oauth.Request.from_consumer_and_token( oauth_consumer, http_method=method, http_url='https://%s:%d%s' % (self.pulp_connection.host, self.pulp_connection.port, url)) oauth_request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), oauth_consumer, None) oauth_header = oauth_request.to_header() # unicode header values causes m2crypto to do odd things. for k, v in oauth_header.items(): oauth_header[k] = encode_unicode(v) headers.update(oauth_header) headers['pulp-user'] = self.pulp_connection.oauth_user connection = httpslib.HTTPSConnection(self.pulp_connection.host, self.pulp_connection.port, ssl_context=ssl_context) try: # Request against the server connection.request(method, url, body=body, headers=headers) response = connection.getresponse() except SSL.SSLError, err: # Translate stale login certificate to an auth exception if 'sslv3 alert certificate expired' == str(err): raise exceptions.ClientCertificateExpiredException( self.pulp_connection.cert_filename) elif 'certificate verify failed' in str(err): raise exceptions.CertificateVerificationException() else: raise exceptions.ConnectionException(None, str(err), None)
def build_oauth_client(): consumer = oauth.Consumer(consumer_key, consumer_secret) token = oauth.Token(xauth_token, xauth_token_secret) client = oauth.Client(consumer, token) client.set_signature_method = oauth.SignatureMethod_HMAC_SHA1() return client
def test_1(self): """Obtaining a Request Token""" response = self.client.get("/oauth/request_token/") self.assertEqual(response.status_code, httplib.UNAUTHORIZED) # depends on REALM_KEY_NAME Django setting self.assertEqual(response._headers['www-authenticate'], ('WWW-Authenticate', 'OAuth realm=""')) self.assertEqual(response.content, 'Invalid request parameters.') # The Consumer sends the following HTTP POST request to the Service Provider parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_signature_method': 'PLAINTEXT', 'oauth_signature': '%s&' % self.CONSUMER_SECRET, 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': 'requestnonce', 'oauth_version': '1.0', 'oauth_callback': 'http://printer.example.com/request_token_ready', 'scope': 'photos', # custom argument to specify Protected Resource } response = self.client.get("/oauth/request_token/", parameters) # The Service Provider checks the signature and replies with an unauthorized # Request Token in the body of the HTTP response:: self.assertEqual(response.status_code, httplib.OK) self.assertTrue("oauth_token_secret=" in response.content) self.assertTrue("oauth_token=" in response.content) self.assertTrue("oauth_callback_confirmed=true" in response.content) token = list(Token.objects.all())[-1] self.assertTrue(token.key in response.content) self.assertTrue(token.secret in response.content) self.assertEqual(token.callback, u'http://printer.example.com/request_token_ready') self.assertTrue(token.callback_confirmed) # If you try to access a resource with a wrong scope, it will return an error:: # This is not supported. # parameters['scope'] = 'videos' # parameters['oauth_nonce'] = 'requestnoncevideos' # response = self.client.get("/oauth/request_token/", parameters) # print "-------" # print response # print "-------" # self.assertEqual(response.status_code, httplib.UNAUTHORIZED) # self.assertEqual(response.content, 'Resource videos does not exist.') parameters['scope'] = 'photos' # restore # If you try to put a wrong callback, it will return an error:: parameters['oauth_callback'] = 'wrongcallback' parameters['oauth_nonce'] = 'requestnoncewrongcallback' response = self.client.get("/oauth/request_token/", parameters) self.assertEqual(response.status_code, httplib.UNAUTHORIZED) self.assertEqual(response.content, 'Invalid callback URL.') # If you do not provide any callback (i.e. oob), the Service Provider SHOULD # display the value of the verification code:: parameters['oauth_callback'] = 'oob' parameters['oauth_nonce'] = 'requestnonceoob' response = self.client.get("/oauth/request_token/", parameters) self.assertEqual(response.status_code, httplib.OK) self.assertTrue("oauth_token_secret=" in response.content) self.assertTrue("oauth_token=" in response.content) self.assertTrue("oauth_callback_confirmed=true" in response.content) oobtoken = list(Token.objects.all())[-1] self.assertTrue(oobtoken.key in response.content) self.assertTrue(oobtoken.secret in response.content) self.assertEqual(oobtoken.callback, None) self.assertFalse(oobtoken.callback_confirmed) # ======== Requesting User Authorization ============ # The Consumer redirects Jane's browser to the Service Provider User # Authorization URL to obtain Jane's approval for accessing her private photos. # The Service Provider asks Jane to sign-in using her username and password:: parameters = { 'oauth_token': token.key, } response = self.client.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, httplib.FOUND) self.assertTrue(True) print response['Location'] self.assertRedirects(response, '/accounts/login/?next=/oauth/authorize/') self.assertTrue(token.key in response['Location']) # If successful, asks her if she approves granting printer.example.com access to # her private photos. If Jane approves the request, the Service Provider # redirects her back to the Consumer's callback URL:: self.assertTrue(self.client.login(username='******', password='******')) self.assertEqual(token.is_approved, 0) response = self.client.get("/oauth/authorize/", parameters) self.assertEqual(response.status_code, httplib.OK) self.assertEqual( response.content, 'Fake authorize view for printer.example.com with params: oauth_token=...' ) # fake authorization by the user parameters['authorize_access'] = 1 response = self.client.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, httplib.FOUND) self.assertRedirects(response, "/request_token_ready") token = Token.objects.get(key=self.token.key) self.assertTrue(token.key in response['Location']) self.assertEqual(token.is_approved, 1) # without session parameter (previous POST removed it) response = self.client.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, httplib.UNAUTHORIZED) self.assertEqual(response.content, 'Action not allowed.') # fake access not granted by the user (set session parameter again) response = self.client.get("/oauth/authorize/", parameters) parameters['authorize_access'] = 0 response = self.client.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, httplib.FOUND) self.assertRedirects(response, "/request_token_ready") self.client.logout() # With OAuth 1.0a, the callback argument can be set to "oob" (out-of-band), # you can specify your own default callback view with the # ``OAUTH_PROVIDER_CALLBACK_VIEW`` setting:: # from oauth_provider.consts import OUT_OF_BAND token.callback = OUT_OF_BAND token.save() parameters = { 'oauth_token': token.key, } self.assertTrue(self.client.login(username='******', password='******')) response = self.client.get("/oauth/authorize/", parameters) parameters['authorize_access'] = 0 response = self.client.post("/oauth/authorize/", parameters) self.assertEqual(response.status_code, httplib.OK) self.assertEqual(response.content, 'Fake callback view.') self.client.logout() # ========== Obtaining an Access Token =========== # Now that the Consumer knows Jane approved the Request Token, it asks the # Service Provider to exchange it for an Access Token:: parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_token': token.key, 'oauth_signature_method': 'PLAINTEXT', 'oauth_signature': '%s&%s' % (self.CONSUMER_SECRET, token.secret), 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': 'accessnonce', 'oauth_version': '1.0', 'oauth_verifier': self.token.verifier, 'scope': 'photos', } response = self.client.get("/oauth/access_token/", parameters) # You can use HTTP Authorization header, if you provide both, header will be # checked before parameters. It depends on your needs. # The Service Provider checks the signature and replies with an Access Token in # the body of the HTTP response:: self.assertEqual(response.status_code, httplib.OK) self.assertTrue('oauth_token_secret=' in response.content) self.assertTrue('oauth_token=' in response.content) access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1] self.assertTrue(access_token.key in response.content) self.assertTrue(access_token.secret in response.content) self.assertEqual(access_token.user.name, u'jane') # The Consumer will not be able to request another Access Token with the same # parameters because the Request Token has been deleted once Access Token is # created:: response = self.client.get("/oauth/access_token/", parameters) self.assertEqual(response.status_code, httplib.BAD_REQUEST) self.assertEqual(response.content, 'Invalid request token.') # The Consumer will not be able to request another Access Token with a missing # or invalid verifier:: new_request_token = Token.objects.create_token( token_type=Token.REQUEST, timestamp=str(int(time.time())), consumer=Consumer.objects.get(key=self.CONSUMER_KEY), user=User.objects.get(username="******"), resource=Resource.objects.get(name='photos')) new_request_token.is_approved = True new_request_token.save() parameters['oauth_token'] = new_request_token.key parameters['oauth_signature'] = '%s&%s' % (self.CONSUMER_SECRET, new_request_token.secret) parameters['oauth_verifier'] = 'invalidverifier' response = self.client.get("/oauth/access_token/", parameters) self.assertEqual(response.status_code, httplib.BAD_REQUEST) self.assertEqual(response.content, 'Invalid OAuth verifier.') parameters['oauth_verifier'] = new_request_token.verifier # restore # The Consumer will not be able to request an Access Token if the token is not # approved:: new_request_token.is_approved = False new_request_token.save() parameters['oauth_nonce'] = 'anotheraccessnonce' response = self.client.get("/oauth/access_token/", parameters) self.assertEqual(response.status_code, httplib.BAD_REQUEST) self.assertEqual(response.content, 'Request Token not approved by the user.') # Accessing Protected Resources # The Consumer is now ready to request the private photo. Since the photo URL is # not secure (HTTP), it must use HMAC-SHA1. # Generating Signature Base String # To generate the signature, it first needs to generate the Signature Base # String. The request contains the following parameters (oauth_signature # excluded) which are ordered and concatenated into a normalized string:: parameters = { 'oauth_consumer_key': self.CONSUMER_KEY, 'oauth_token': access_token.key, 'oauth_signature_method': 'HMAC-SHA1', 'oauth_timestamp': str(int(time.time())), 'oauth_nonce': 'accessresourcenonce', 'oauth_version': '1.0', } # Calculating Signature Value # HMAC-SHA1 produces the following digest value as a base64-encoded string # (using the Signature Base String as text and kd94hf93k423kf44&pfkkdhi9sl3r4s00 # as key):: import oauth2 as oauth oauth_request = oauth.Request.from_token_and_callback( access_token, http_url='http://testserver/oauth/photo/', parameters=parameters) signature_method = oauth.SignatureMethod_HMAC_SHA1() signature = signature_method.sign(oauth_request, self.consumer, access_token) # Requesting Protected Resource # All together, the Consumer request for the photo is:: parameters['oauth_signature'] = signature response = self.client.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, httplib.OK) self.assertEqual(response.content, 'Protected Resource access!') # Otherwise, an explicit error will be raised:: parameters['oauth_signature'] = 'wrongsignature' parameters['oauth_nonce'] = 'anotheraccessresourcenonce' response = self.client.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, httplib.UNAUTHORIZED) self.assertTrue( 'Invalid signature. Expected signature base string: GET' in response.content) response = self.client.get("/oauth/photo/") self.assertEqual(response.status_code, httplib.UNAUTHORIZED) self.assertEqual(response.content, 'Invalid request parameters.') # Revoking Access # If Jane deletes the Access Token of printer.example.com, the Consumer will not # be able to access the Protected Resource anymore:: access_token.delete() # Note that an "Invalid signature" error will be raised here if the # token is not revoked by Jane because we reuse a previously used one. parameters['oauth_signature'] = signature parameters['oauth_nonce'] = 'yetanotheraccessresourcenonce' response = self.client.get("/oauth/photo/", parameters) self.assertEqual(response.status_code, httplib.UNAUTHORIZED) self.assertTrue('Invalid access token: ...', response.content)
# See assignment1.html instructions or README for how to get these credentials api_key = "g0qzK8JjEjGlmMDepLZrUU6CL" api_secret = "aBwgGAxBHFPO6MnDsQJ2f8ZYH6fMyHA9m9u3mtWrQ8KdKlFiW9" access_token_key = "23799954-o394XpQMtfEiAZ3zWqWUAIFHgl8Vl3lNRqEC7dlSc" access_token_secret = "qqRghb9Ci7dHLjQlot62KuTrlhoRh0rLWrU3JZYntO4hU" _debug = 0 oauth_token = oauth.Token(key=access_token_key, secret=access_token_secret) oauth_consumer = oauth.Consumer(key=api_key, secret=api_secret) signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1() http_method = "GET" http_handler = urllib.HTTPHandler(debuglevel=_debug) https_handler = urllib.HTTPSHandler(debuglevel=_debug) ''' Construct, sign, and open a twitter request using the hard-coded credentials above. ''' def twitterreq(url, method, parameters): req = oauth.Request.from_consumer_and_token(oauth_consumer, token=oauth_token, http_method=http_method,
def test_minimal(self): r"""Test a minimal 2-legged scenario""" app = self._make_app() # Without authentication we are not allowed in res = app.get('http://localhost/secret-for-all', expect_errors=True) self.assertTrue('401 Unauthorized' in res) # We also get a WWW-Authenticate header self.assertEquals(res.header('WWW-Authenticate'), 'OAuth realm="OAuthRealm"') # Now create a proper request with OAuth parameters consumer = oauth.Consumer(key='app', secret='app-secret') o_req = oauth.Request.from_consumer_and_token(consumer, token=None, http_method='GET', http_url='http://localhost/secret-for-all') o_req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) request_header = o_req.to_header() request_header['Authorization'] = str(request_header['Authorization']) res = app.get(o_req.url, expect_errors=True, headers=request_header) # Still no go self.assertTrue('401 Unauthorized' in res) # Now create this consumer in our DB and try again self.session.add(Consumer(key='app', secret='app-secret')) self.session.flush() # The new consumer was really created self.assertEquals(self.plugin.manager.get_consumer_by_key('app').key, consumer.key) res = app.get(o_req.url, headers=request_header) # Here we go - the resource we wanted so much self.assertTrue('This is a secret for all to see' in res) # However we fail to get the resource for app1 o_req = oauth.Request.from_consumer_and_token(consumer, token=None, http_method='GET', http_url='http://localhost/secret-for-app1') o_req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) request_header = o_req.to_header() request_header['Authorization'] = str(request_header['Authorization']) res = app.get(o_req.url, expect_errors=True, headers=request_header) self.assertTrue('401 Unauthorized' in res) # So that means we need another consumer consumer1 = oauth.Consumer(key='app1', secret='app-secret') # And in DB as well self.session.add(Consumer(key='app1', secret='app1-secret')) self.session.flush() # The new consumer was created self.assertEquals(self.plugin.manager.get_consumer_by_key('app1').key, consumer1.key) # Now it should work o_req = oauth.Request.from_consumer_and_token(consumer1, token=None, http_method='GET', http_url='http://localhost/secret-for-app1') o_req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer1, None) request_header = o_req.to_header() request_header['Authorization'] = str(request_header['Authorization']) res = app.get(o_req.url, expect_errors=True, headers=request_header) self.assertTrue('401 Unauthorized' in res) # What's wrong? Oh, the secret! consumer1.secret = 'app1-secret' o_req = oauth.Request.from_consumer_and_token(consumer1, token=None, http_method='GET', http_url='http://localhost/secret-for-app1') o_req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer1, None) request_header = o_req.to_header() request_header['Authorization'] = str(request_header['Authorization']) res = app.get(o_req.url, headers=request_header) self.assertTrue('This is a secret for app1 only' in res) # We should not be able to access not_oauth protected resource neither # with consumer1... o_req = oauth.Request.from_consumer_and_token(consumer1, token=None, http_method='GET', http_url='http://localhost/secret-for-others') o_req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer1, None) request_header = o_req.to_header() request_header['Authorization'] = str(request_header['Authorization']) res = app.get(o_req.url, expect_errors=True, headers=request_header) self.assertTrue('401 Unauthorized' in res) # nor with consumer... o_req = oauth.Request.from_consumer_and_token(consumer, token=None, http_method='GET', http_url='http://localhost/secret-for-others') o_req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) request_header = o_req.to_header() request_header['Authorization'] = str(request_header['Authorization']) res = app.get(o_req.url, expect_errors=True, headers=request_header) self.assertTrue('401 Unauthorized' in res) # However, a simple unauthenticated request will do res = app.get(o_req.url) self.assertTrue('This is for all except oauth' in res)