def compute_from_request(request): """ Computes the signature based on the data stored in request object. """ verb = request.method absolute_uri = request.build_absolute_uri() uri = NormalizedUri(absolute_uri, request.META).get_uri() try: timestamp = search_key(request.META, request.GET, 'timestamp') consumer_key = search_key(request.META, request.GET, 'consumer_key') nonce = None if config('nonce'): nonce = search_key(request.META, request.GET, 'nonce') except KeyNotFound: raise _AuthException("Invalid Request. Some arguments are missing.") # A request is timedout if its life is longer than the value specified # in API_AUTH_TIMEOUT. try: if int(time.time()) > int(timestamp) + config('timeout'): raise _AuthException("The request has timed out. " "Expected timestamp: %s." % int(time.time())) except ValueError: raise _AuthException("Invalid timestamp format. Must be integer.") body = request.body consumer = Consumer(consumer_key) secret = consumer.get_secret_key() signature = Signature.compute_signature(secret, verb, uri, timestamp, consumer_key, body, nonce) return Signature(signature)
def test_search_key(self): dict1 = {"HTTP_A": 1, "HTTP_B": 2} dict2 = {"b": 3, "c": 4} value = utils.search_key(dict1, dict2, "a") self.assertEqual(value, 1) value = utils.search_key(dict1, dict2, "b") self.assertEqual(value, 2) value = utils.search_key(dict1, dict2, "c") self.assertEqual(value, 4) self.assertRaises(utils.KeyNotFound, utils.search_key, dict1, dict2, "x")
def extract_from_request(request): """ Search for signature in headers and in get arguments. """ try: sig = search_key(request.META, request.GET, 'signature') except KeyNotFound: raise _AuthException("Signature not found in request.") return Signature(sig)
def is_authenticated(self, request): """ This method is required by Piston to implement custom authentication protocol. It must return True if the authentication is successful. It's also good practice to set request.user and other fields to certain values that can be used in other places. In case the authentication was successful a signal is emitted to allow further customisation. """ try: incoming = Signature.extract_from_request(request) computed = Signature.compute_from_request(request) if not incoming == computed: msg = "Signatures don't match. Expecting %s." % computed return self.handle_error(msg, request) consumer_key = search_key(request.META, request.GET, 'consumer_key') # Check the nonce last so we minimize the db hit. self.check_nonce(request.META, request.GET, consumer_key) except (_AuthException, KeyNotFound), e: return self.handle_error(e, request)
def check_nonce(self, meta, get, consumer_key): if config('nonce'): nonce = search_key(meta, get, 'nonce') consumer = Consumer(consumer_key) consumer.validate_nonce(nonce)