summary refs log tree commit diff
path: root/synapse/handlers/auth.py
diff options
context:
space:
mode:
authorDaniel Wagner-Hall <daniel@matrix.org>2015-08-20 16:21:35 +0100
committerDaniel Wagner-Hall <daniel@matrix.org>2015-08-20 16:21:35 +0100
commitcecbd636e94f4e900ef6d246b62698ff1c8ee352 (patch)
treeb5a53e2a02201cd37ea33090c630865f593c19bd /synapse/handlers/auth.py
parents/by_token/by_access_token/g (diff)
downloadsynapse-cecbd636e94f4e900ef6d246b62698ff1c8ee352.tar.xz
/tokenrefresh POST endpoint
This allows refresh tokens to be exchanged for (access_token,
refresh_token).

It also starts issuing them on login, though no clients currently
interpret them.
Diffstat (limited to 'synapse/handlers/auth.py')
-rw-r--r--synapse/handlers/auth.py35
1 files changed, 30 insertions, 5 deletions
diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py
index 0bf917efdd..65bd8189dc 100644
--- a/synapse/handlers/auth.py
+++ b/synapse/handlers/auth.py
@@ -279,15 +279,18 @@ class AuthHandler(BaseHandler):
             user_id (str): User ID
             password (str): Password
         Returns:
-            The access token for the user's session.
+            A tuple of:
+              The access token for the user's session.
+              The refresh token for the user's session.
         Raises:
             StoreError if there was a problem storing the token.
             LoginError if there was an authentication problem.
         """
         yield self._check_password(user_id, password)
         logger.info("Logging in user %s", user_id)
-        token = yield self.issue_access_token(user_id)
-        defer.returnValue(token)
+        access_token = yield self.issue_access_token(user_id)
+        refresh_token = yield self.issue_refresh_token(user_id)
+        defer.returnValue((access_token, refresh_token))
 
     @defer.inlineCallbacks
     def _check_password(self, user_id, password):
@@ -304,11 +307,16 @@ class AuthHandler(BaseHandler):
 
     @defer.inlineCallbacks
     def issue_access_token(self, user_id):
-        reg_handler = self.hs.get_handlers().registration_handler
-        access_token = reg_handler.generate_access_token(user_id)
+        access_token = self.generate_access_token(user_id)
         yield self.store.add_access_token_to_user(user_id, access_token)
         defer.returnValue(access_token)
 
+    @defer.inlineCallbacks
+    def issue_refresh_token(self, user_id):
+        refresh_token = self.generate_refresh_token(user_id)
+        yield self.store.add_refresh_token_to_user(user_id, refresh_token)
+        defer.returnValue(refresh_token)
+
     def generate_access_token(self, user_id):
         macaroon = pymacaroons.Macaroon(
             location = self.hs.config.server_name,
@@ -323,6 +331,23 @@ class AuthHandler(BaseHandler):
 
         return macaroon.serialize()
 
+    def generate_refresh_token(self, user_id):
+        m = self._generate_base_macaroon(user_id)
+        m.add_first_party_caveat("type = refresh")
+        # Important to add a nonce, because otherwise every refresh token for a
+        # user will be the same.
+        m.add_first_party_caveat("nonce = %s" % stringutils.random_string_with_symbols(16))
+        return m.serialize()
+
+    def _generate_base_macaroon(self, user_id):
+        macaroon = pymacaroons.Macaroon(
+            location = self.hs.config.server_name,
+            identifier = "key",
+            key = self.hs.config.macaroon_secret_key)
+        macaroon.add_first_party_caveat("gen = 1")
+        macaroon.add_first_party_caveat("user_id = %s" % (user_id,))
+        return macaroon
+
     @defer.inlineCallbacks
     def set_password(self, user_id, newpassword):
         password_hash = bcrypt.hashpw(newpassword, bcrypt.gensalt())