From 143fb346521f07e20c0cb93073dbb6cfeab6fe43 Mon Sep 17 00:00:00 2001 From: Joe Stump Date: Mon, 12 Oct 2009 20:51:05 -0600 Subject: [PATCH] Changed setter to attr per termie's notes. Removed all references to DataStore code. --- oauth/__init__.py | 169 +++++++------------------------------------- tests/test_oauth.py | 46 ++++++------ 2 files changed, 49 insertions(+), 166 deletions(-) diff --git a/oauth/__init__.py b/oauth/__init__.py index b19c8ac4..d8ad5b7e 100644 --- a/oauth/__init__.py +++ b/oauth/__init__.py @@ -205,8 +205,8 @@ def __str__(self): return self.to_string() -def setter(setter): - name = setter.__name__ +def setter(attr): + name = attr.__name__ def getter(self): try: @@ -217,7 +217,7 @@ def getter(self): def deleter(self): del self.__dict__[name] - return property(getter, setter, deleter) + return property(getter, attr, deleter) class Request(dict): @@ -291,6 +291,11 @@ def to_postdata(self): def to_url(self): """Serialize as a URL for a GET request.""" return '%s?%s' % (self.url, self.to_postdata()) + + def get_parameter(self, parameter): + ret = self.get(parameter) + if ret is None: + raise Error('Parameter not found: %s' % parameter) def get_normalized_parameters(self): """Return a string that contains the parameters that must be signed.""" @@ -416,73 +421,22 @@ class Server(object): This class implements the logic to check requests for authorization. You can use it with your web server or web framework to protect certain resources with OAuth. - - As this class has no knowledge of how your application stores data, you - have to give it an object it can use to load OAuth objects. Implement a - subclass of `oauth.interface.DataStore` for your storage system and supply - it to the `Server` instance as `data_store`. """ timestamp_threshold = 300 # In seconds, five minutes. version = VERSION signature_methods = None - data_store = None - def __init__(self, data_store=None, signature_methods=None): - self.data_store = data_store + def __init__(self, signature_methods=None): self.signature_methods = signature_methods or {} - def set_data_store(self, data_store): - self.data_store = data_store - - def get_data_store(self): - return self.data_store - def add_signature_method(self, signature_method): self.signature_methods[signature_method.name] = signature_method return self.signature_methods - def fetch_request_token(self, oauth_request): - """Processes a request_token request and returns the - request token on success. - """ - try: - # Get the request token for authorization. - token = self._get_token(oauth_request, 'request') - except Error: - # No token required for the initial token request. - version = self._get_version(oauth_request) - consumer = self._get_consumer(oauth_request) - try: - callback = self.get_callback(oauth_request) - except Error: - callback = None # 1.0, no callback specified. - self._check_signature(oauth_request, consumer, None) - # Fetch a new token. - token = self.data_store.fetch_request_token(consumer, callback) - return token - - def fetch_access_token(self, oauth_request): - """Processes an access_token request and returns the - access token on success. - """ - version = self._get_version(oauth_request) - consumer = self._get_consumer(oauth_request) - try: - verifier = self._get_verifier(oauth_request) - except Error: - verifier = None - # Get the request token. - token = self._get_token(oauth_request, 'request') - self._check_signature(oauth_request, consumer, token) - new_token = self.data_store.fetch_access_token(consumer, - token, verifier) - - return new_token - - def verify_request(self, oauth_request): + def verify_request(self, request, consumer, token): """Verifies an api call and checks all the parameters.""" - # -> consumer and token + version = self._get_version(oauth_request) consumer = self._get_consumer(oauth_request) # Get the access token. @@ -491,33 +445,26 @@ def verify_request(self, oauth_request): parameters = oauth_request.get_nonoauth_parameters() return consumer, token, parameters - def authorize_token(self, token, user): - """Authorize a request token.""" - return self.data_store.authorize_request_token(token, user) - - def get_callback(self, oauth_request): - """Get the callback URL.""" - return oauth_request.get_parameter('oauth_callback') - def build_authenticate_header(self, realm=''): """Optional support for the authenticate header.""" return {'WWW-Authenticate': 'OAuth realm="%s"' % realm} - def _get_version(self, oauth_request): + def _get_version(self, request): """Verify the correct version request for this server.""" try: - version = oauth_request.get_parameter('oauth_version') + version = request.get_parameter('oauth_version') except: version = VERSION + if version and version != self.version: raise Error('OAuth version %s not supported.' % str(version)) + return version - def _get_signature_method(self, oauth_request): + def _get_signature_method(self, request): """Figure out the signature with some defaults.""" try: - signature_method = oauth_request.get_parameter( - 'oauth_signature_method') + signature_method = request.get_parameter('oauth_signature_method') except: signature_method = SIGNATURE_METHOD try: @@ -530,48 +477,29 @@ def _get_signature_method(self, oauth_request): return signature_method - def _get_consumer(self, oauth_request): - consumer_key = oauth_request.get_parameter('oauth_consumer_key') - consumer = self.data_store.lookup_consumer(consumer_key) - if not consumer: - raise Error('Invalid consumer.') - return consumer - - def _get_token(self, oauth_request, token_type='access'): - """Try to find the token for the provided request token key.""" - token_field = oauth_request.get_parameter('oauth_token') - token = self.data_store.lookup_token(token_type, token_field) - if not token: - raise Error('Invalid %s token: %s' % (token_type, token_field)) - return token - - def _get_verifier(self, oauth_request): - return oauth_request.get_parameter('oauth_verifier') + def _get_verifier(self, request): + return request.get_parameter('oauth_verifier') - def _check_signature(self, oauth_request, consumer, token): - timestamp, nonce = oauth_request._get_timestamp_nonce() + def _check_signature(self, request, consumer, token): + timestamp, nonce = request._get_timestamp_nonce() self._check_timestamp(timestamp) - self._check_nonce(consumer, token, nonce) - signature_method = self._get_signature_method(oauth_request) + signature_method = self._get_signature_method(request) try: - signature = oauth_request.get_parameter('oauth_signature') + signature = request.get_parameter('oauth_signature') except: raise Error('Missing signature.') # Validate the signature. - valid_sig = signature_method.check_signature(oauth_request, consumer, - token, signature) + valid = signature_method.check(request, consumer, token, signature) - if not valid_sig: - key, base = signature_method.signing_base( - oauth_request, consumer, token) + if not valid: + key, base = signature_method.signing_base(request, consumer, token) raise Error('Invalid signature. Expected signature base ' 'string: %s' % base) - built = signature_method.sign(oauth_request, - consumer, token) + built = signature_method.sign(request, consumer, token) def _check_timestamp(self, timestamp): """Verify that timestamp is recentish.""" @@ -583,12 +511,6 @@ def _check_timestamp(self, timestamp): 'greater difference than threshold %d' % (timestamp, now, self.timestamp_threshold)) - def _check_nonce(self, consumer, token, nonce): - """Verify that the nonce is uniqueish.""" - nonce = self.data_store.lookup_nonce(consumer, token, nonce) - if nonce: - raise Error('Nonce already used: %s' % str(nonce)) - class Client(object): """OAuthClient is a worker to attempt to execute a request.""" @@ -618,42 +540,6 @@ def access_resource(self, oauth_request): raise NotImplementedError -class DataStore(object): - """A database abstraction used to lookup consumers and tokens. - - To use your backend store with the `oauth` module, implement a subclass of - this class that performs its methods using your database or storage - system. Then, when using `oauth.Server`, supply it with an instance of - your custom `DataStore` class to have objects stored in natively in your - own data store. - - """ - - def lookup_consumer(self, key): - """-> OAuthConsumer.""" - raise NotImplementedError - - def lookup_token(self, oauth_consumer, token_type, token_token): - """-> OAuthToken.""" - raise NotImplementedError - - def lookup_nonce(self, oauth_consumer, oauth_token, nonce): - """-> OAuthToken.""" - raise NotImplementedError - - def fetch_request_token(self, oauth_consumer, oauth_callback): - """-> OAuthToken.""" - raise NotImplementedError - - def fetch_access_token(self, oauth_consumer, oauth_token, oauth_verifier): - """-> OAuthToken.""" - raise NotImplementedError - - def authorize_request_token(self, oauth_token, user): - """-> OAuthToken.""" - raise NotImplementedError - - class SignatureMethod(object): """A way of signing requests. @@ -748,7 +634,6 @@ def sign(self, request, consumer, token): OAuthRequest = Request OAuthServer = Server OAuthClient = Client -OAuthDataStore = DataStore OAuthSignatureMethod = SignatureMethod OAuthSignatureMethod_HMAC_SHA1 = SignatureMethod_HMAC_SHA1 OAuthSignatureMethod_PLAINTEXT = SignatureMethod_PLAINTEXT diff --git a/tests/test_oauth.py b/tests/test_oauth.py index 95ae5a3f..cfb3a9dd 100644 --- a/tests/test_oauth.py +++ b/tests/test_oauth.py @@ -443,39 +443,34 @@ def test_from_token_and_callback(self): self.assertTrue('oauth_callback' in req) self.assertEquals(req['oauth_callback'], url) -class MyDataStore(oauth.DataStore): - def lookup_consumer(self, key): - if key == "test-consumer-key": - return oauth.Consumer(key="test-consumer-key", - secret="test-consumer-secret") - - return None - - def lookup_token(self, consumer, type, token): - if type == "request": - return oauth.Token(key="test-request-token-key", - secret="test-request-token-secret") - elif type == "access": - return oauth.Token(key="test-access-token-key", - secret="test-access-token-secret") - - return None - -BadDataStore = oauth.DataStore - class TestServer(unittest.TestCase): def test_init(self): - server = oauth.Server(data_store=MyDataStore(), - signature_methods={'HMAC-SHA1' : oauth.SignatureMethod_HMAC_SHA1()}) - self.assertTrue(isinstance(server.data_store, MyDataStore)) + server = oauth.Server(signature_methods={'HMAC-SHA1' : oauth.SignatureMethod_HMAC_SHA1()}) self.assertTrue('HMAC-SHA1' in server.signature_methods) self.assertTrue(isinstance(server.signature_methods['HMAC-SHA1'], oauth.SignatureMethod_HMAC_SHA1)) server = oauth.Server() - self.assertEquals(server.data_store, None) self.assertEquals(server.signature_methods, {}) + def _req(self): + ds = MyDataStore() + + url = "http://sp.example.com/" + + params = { + 'oauth_version': "1.0", + 'oauth_nonce': "4572616e48616d6d65724c61686176", + 'oauth_timestamp': "137131200" + } + + con = ds.lookup_consumer("test-consumer-key") + tok = ds.lookup_token(con, "request", "test-request-token-key") + + params['oauth_token'] = tok.key + params['oauth_consumer_key'] = con.key + return oauth.Request(method="GET", url=url, parameters=params) + def test_add_signature_method(self): server = oauth.Server() res = server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1()) @@ -493,6 +488,9 @@ def test_add_signature_method(self): def test_fetch_request_token(self): pass +# server = oauth.Server(data_store=MyDataStore()) +# token = server.fetch_request_token(self._req()) + def test_bad_token_fetch_request_token(self): pass