summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2013-04-25 23:15:06 -0300
committerdrebs <drebs@leap.se>2013-04-25 23:15:06 -0300
commitcc9537b9c73c6f502dc4576df0aee4409e887d47 (patch)
tree368b8e4d690d2cdf18f87f2d0e78f4afdb3b8153
parent2ef514b02fa37a0a2ebac0bb9668543e29033a7f (diff)
Add token auth infrastructure.
-rw-r--r--src/leap/soledad/__init__.py4
-rw-r--r--src/leap/soledad/backends/leap_backend.py12
-rw-r--r--src/leap/soledad/server.py46
3 files changed, 38 insertions, 24 deletions
diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py
index a736d32b..06f7c755 100644
--- a/src/leap/soledad/__init__.py
+++ b/src/leap/soledad/__init__.py
@@ -667,7 +667,7 @@ class Soledad(object):
"""
return self._db.resolve_doc(doc, conflicted_doc_revs)
- def sync(self, url):
+ def sync(self, url, creds=None):
"""
Synchronize the local encrypted replica with a remote replica.
@@ -679,7 +679,7 @@ class Soledad(object):
@rtype: str
"""
# TODO: create authentication scheme for sync with server.
- local_gen = self._db.sync(url, creds=None, autocreate=True)
+ local_gen = self._db.sync(url, creds=creds, autocreate=True)
events.signal(events.events_pb2.SOLEDAD_DONE_DATA_SYNC, self._address)
return local_gen
diff --git a/src/leap/soledad/backends/leap_backend.py b/src/leap/soledad/backends/leap_backend.py
index 05c27bc1..51c471eb 100644
--- a/src/leap/soledad/backends/leap_backend.py
+++ b/src/leap/soledad/backends/leap_backend.py
@@ -394,3 +394,15 @@ class LeapSyncTarget(HTTPSyncTarget):
res = self._parse_sync_stream(data, return_doc_cb, ensure_callback)
data = None
return res['new_generation'], res['new_transaction_id']
+
+ def set_token_credentials(self, address, token):
+ self._creds = {'token': (address, token)}
+
+ def _sign_request(self, method, url_query, params):
+ if 'token' in self._creds:
+ address, token = self._creds['token']
+ auth = '%s:%s' % (address, token)
+ return [('Authorization', 'Token %s' % auth.encode('base64'))]
+ else:
+ return HTTPSyncTarget._sign_request(
+ self, method, url_query, params)
diff --git a/src/leap/soledad/server.py b/src/leap/soledad/server.py
index fdb98916..3d3c6f69 100644
--- a/src/leap/soledad/server.py
+++ b/src/leap/soledad/server.py
@@ -116,36 +116,34 @@ class SoledadAuthMiddleware(object):
"""
if self.prefix and not environ['PATH_INFO'].startswith(self.prefix):
return self._error(start_response, 400, "bad request")
+ auth = environ.get('HTTP_AUTHORIZATION')
+ if not auth:
+ return self._error(start_response, 401, "unauthorized",
+ "Missing Token Authentication.")
+ scheme, encoded = auth.split(None, 1)
+ if scheme.lower() != 'token':
+ return self._error(
+ start_response, 401, "unauthorized",
+ "Missing Token Authentication")
+ address, token = encoded.decode('base64').split(':', 1)
+ try:
+ self.verify_token(environ, address, token)
+ except Unauthorized:
+ return self._error(
+ start_response, 401, "unauthorized",
+ "Incorrect address or token.")
+ del environ['HTTP_AUTHORIZATION']
shift_path_info(environ)
- qs = parse_qs(environ.get('QUERY_STRING'), strict_parsing=True)
- if 'auth_token' not in qs:
- if self.need_auth(environ):
- return self._error(start_response, 401, "unauthorized",
- "Missing Authentication Token.")
- else:
- token = qs['auth_token'][0]
- try:
- self.verify_token(environ, token)
- except Unauthorized:
- return self._error(
- start_response, 401, "unauthorized",
- "Incorrect password or login.")
- # remove auth token from query string.
- del qs['auth_token']
- qs_str = ''
- if qs:
- qs_str = reduce(lambda x, y: '&'.join([x, y]),
- map(lambda (x, y): '='.join([x, str(y)]),
- qs.iteritems()))
- environ['QUERY_STRING'] = qs_str
return self.app(environ, start_response)
- def verify_token(self, environ, token):
+ def verify_token(self, environ, address, token):
"""
Verify if token is valid for authenticating this request.
@param environ: Dictionary containing CGI variables.
@type environ: dict
+ @param token: The user address.
+ @type token: str
@param token: The authentication token.
@type token: str
@@ -195,6 +193,10 @@ class SoledadApp(http_app.HTTPApp):
@return: HTTP application results.
@rtype: list
"""
+ # TODO: this is a hack for tests to pass, we should remove it asap.
+ #if environ['CONTENT_LENGTH'] == '':
+ # environ['CONTENT_LENGTH'] = 1
+ #import ipdb; ipdb.set_trace()
return http_app.HTTPApp.__call__(self, environ, start_response)