Permalink
Browse files

Changed setter to attr per termie's notes. Removed all references to …

…DataStore code.
  • Loading branch information...
joestump committed Oct 13, 2009
1 parent cd86628 commit 143fb346521f07e20c0cb93073dbb6cfeab6fe43
Showing with 49 additions and 166 deletions.
  1. +27 −142 oauth/__init__.py
  2. +22 −24 tests/test_oauth.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
@@ -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

0 comments on commit 143fb34

Please sign in to comment.