From 39d32b58ba555c26ac821c75b700ca1f560e99c0 Mon Sep 17 00:00:00 2001 From: albertony <12441419+albertony@users.noreply.github.com> Date: Thu, 23 Jun 2022 11:11:39 +0200 Subject: [PATCH 1/3] Added support for v2 authid with cli tokens --- cli-token.html | 1 + main.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/cli-token.html b/cli-token.html index 0f87b89..c510531 100644 --- a/cli-token.html +++ b/cli-token.html @@ -25,6 +25,7 @@

{{appname}} for {{service}}

Type in the CLI token

+

diff --git a/main.py b/main.py index 8141d3c..a54a306 100644 --- a/main.py +++ b/main.py @@ -172,8 +172,8 @@ def get(self): if self.request.get('token', None) is not None: link += '&token=' + self.request.get('token') - if tokenversion is not None: - link += '&tokenversion=' + str(tokenversion) + if tokenversion is not None: + link += '&tokenversion=' + str(tokenversion) notes = '' if n.has_key('notes'): @@ -396,7 +396,8 @@ def get(self): 'service': provider['display'], 'appname': settings.APP_NAME, 'longappname': settings.SERVICE_DISPLAYNAME, - 'id': provider['id'] + 'id': provider['id'], + 'tokenversion': self.request.get('tokenversion', '') } template = JINJA_ENVIRONMENT.get_template('cli-token.html') @@ -414,6 +415,12 @@ def post(self): provider, service = find_provider_and_service(id) display = provider['display'] + tokenversion = None + try: + tokenversion = int(self.request.POST.get('tokenversion')) + except: + pass + try: data = self.request.POST.get('token') content = base64.urlsafe_b64decode(str(data) + '=' * (-len(data) % 4)) @@ -444,6 +451,28 @@ def post(self): resp = json.loads(content) + # v2 tokens are just the provider name and the refresh token + # and they have no stored state on the server + if tokenversion == 2: + authid = 'v2:' + id + ':' + resp['refresh_token'] + fetchtoken = dbmodel.create_fetch_token(resp) + dbmodel.update_fetch_token(fetchtoken, authid) + + # Report results to the user + template_values = { + 'service': display, + 'appname': settings.APP_NAME, + 'longappname': settings.SERVICE_DISPLAYNAME, + 'authid': authid, + 'fetchtoken': fetchtoken + } + + template = JINJA_ENVIRONMENT.get_template('logged-in.html') + self.response.write(template.render(template_values)) + + logging.info('Returned refresh token for service %s', id) + return + keyid, authid = create_authtoken(id, resp) fetchtoken = dbmodel.create_fetch_token(resp) From 3f07323447cd4c8d80052e0fbff4944622a31841 Mon Sep 17 00:00:00 2001 From: albertony <12441419+albertony@users.noreply.github.com> Date: Thu, 23 Jun 2022 16:06:08 +0200 Subject: [PATCH 2/3] Disable support for v2 authid with Jottacloud since it uses refresh token rotation --- main.py | 21 +++++++++++++++++---- settings.py | 3 ++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index a54a306..8e13c1d 100644 --- a/main.py +++ b/main.py @@ -329,6 +329,10 @@ def get(self, service=None): # v2 tokens are just the provider name and the refresh token # and they have no stored state on the server if statetoken.version == 2: + + if service.has_key('refresh-token-rotation') and service['refresh-token-rotation']: + raise Exception('Error: This service uses refresh token rotation which is not compatible with AuthID v2') + authid = 'v2:' + statetoken.service + ':' + resp['refresh_token'] dbmodel.update_fetch_token(statetoken.fetchtoken, authid) @@ -427,7 +431,7 @@ def post(self): resp = json.loads(content) except: error = 'Error: Invalid CLI token' - raise + raise Exception(error) urlfetch.set_default_fetch_deadline(20) url = service['auth-url'] @@ -454,6 +458,11 @@ def post(self): # v2 tokens are just the provider name and the refresh token # and they have no stored state on the server if tokenversion == 2: + + if service.has_key('refresh-token-rotation') and service['refresh-token-rotation']: + error = 'Error: This service uses refresh token rotation which is not compatible with AuthID v2' + raise Exception(error) + authid = 'v2:' + id + ':' + resp['refresh_token'] fetchtoken = dbmodel.create_fetch_token(resp) dbmodel.update_fetch_token(fetchtoken, authid) @@ -742,9 +751,13 @@ def process(self, authid): logging.info('Caching response to: %s for %s secs, service: %s', keyid, exp_secs - 10, servicetype) # Write the result back to the client - self.response.write(json.dumps( - {'access_token': resp['access_token'], 'expires': exp_secs, 'type': servicetype, - 'v2_authid': 'v2:' + entry.service + ':' + rt})) + if service.has_key('refresh-token-rotation') and service['refresh-token-rotation']: + self.response.write(json.dumps( + {'access_token': resp['access_token'], 'expires': exp_secs, 'type': servicetype})) + else: + self.response.write(json.dumps( + {'access_token': resp['access_token'], 'expires': exp_secs, 'type': servicetype, + 'v2_authid': 'v2:' + entry.service + ':' + rt})) except: logging.exception('handler error for ' + servicetype) diff --git a/settings.py b/settings.py index 7252425..f3497a5 100644 --- a/settings.py +++ b/settings.py @@ -234,7 +234,8 @@ 'display': 'Jottacloud', 'client-id': "jottacli", 'auth-url': JOTTACLOUD_AUTH_URL, - 'cli-token': True + 'cli-token': True, + 'refresh-token-rotation': True } } From e9281f26d350d2d1b6dcb5f5d1c440de443af4fb Mon Sep 17 00:00:00 2001 From: albertony <12441419+albertony@users.noreply.github.com> Date: Thu, 23 Jun 2022 17:16:47 +0200 Subject: [PATCH 3/3] Fix automatic fetch of AuthID from cli token --- cli-token.html | 1 + main.py | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cli-token.html b/cli-token.html index c510531..3632cdc 100644 --- a/cli-token.html +++ b/cli-token.html @@ -25,6 +25,7 @@

{{appname}} for {{service}}

Type in the CLI token

+
diff --git a/main.py b/main.py index 8e13c1d..32b42e6 100644 --- a/main.py +++ b/main.py @@ -169,8 +169,9 @@ def get(self): link = '/cli-token?id=' + n['id'] else: link = '/login?id=' + n['id'] - if self.request.get('token', None) is not None: - link += '&token=' + self.request.get('token') + + if self.request.get('token', None) is not None: + link += '&token=' + self.request.get('token') if tokenversion is not None: link += '&tokenversion=' + str(tokenversion) @@ -401,6 +402,7 @@ def get(self): 'appname': settings.APP_NAME, 'longappname': settings.SERVICE_DISPLAYNAME, 'id': provider['id'], + 'fetchtoken': self.request.get('token', ''), 'tokenversion': self.request.get('tokenversion', '') } @@ -419,6 +421,8 @@ def post(self): provider, service = find_provider_and_service(id) display = provider['display'] + fetchtoken = self.request.POST.get('fetchtoken', None) + tokenversion = None try: tokenversion = int(self.request.POST.get('tokenversion')) @@ -464,7 +468,6 @@ def post(self): raise Exception(error) authid = 'v2:' + id + ':' + resp['refresh_token'] - fetchtoken = dbmodel.create_fetch_token(resp) dbmodel.update_fetch_token(fetchtoken, authid) # Report results to the user @@ -484,8 +487,6 @@ def post(self): keyid, authid = create_authtoken(id, resp) - fetchtoken = dbmodel.create_fetch_token(resp) - # If this was part of a polling request, signal completion dbmodel.update_fetch_token(fetchtoken, authid)