From 05c4b6012eac68e64294edaa213606c366e27b73 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 8 Feb 2019 21:39:45 +0100 Subject: [PATCH] Calculate expiry date to determine if token refresh is needed --- cura/API/Account.py | 1 - cura/OAuth2/AuthorizationHelpers.py | 9 ++++++--- cura/OAuth2/AuthorizationRequestHandler.py | 1 - cura/OAuth2/AuthorizationService.py | 20 +++++++++++--------- cura/OAuth2/Models.py | 3 ++- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/cura/API/Account.py b/cura/API/Account.py index a04f97ef1c..8a8b708cfa 100644 --- a/cura/API/Account.py +++ b/cura/API/Account.py @@ -57,7 +57,6 @@ class Account(QObject): def initialize(self) -> None: self._authorization_service.initialize(self._application.getPreferences()) - self._authorization_service.onAuthStateChanged.connect(self._onLoginStateChanged) self._authorization_service.onAuthenticationError.connect(self._onLoginStateChanged) self._authorization_service.loadAuthDataFromPreferences() diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py index 87b8c45d6d..d1ba60fcd6 100644 --- a/cura/OAuth2/AuthorizationHelpers.py +++ b/cura/OAuth2/AuthorizationHelpers.py @@ -1,10 +1,11 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from datetime import datetime import json import random from hashlib import sha512 from base64 import b64encode -from typing import Dict, Optional +from typing import Optional import requests @@ -75,7 +76,8 @@ class AuthorizationHelpers: access_token=token_data["access_token"], refresh_token=token_data["refresh_token"], expires_in=token_data["expires_in"], - scope=token_data["scope"]) + scope=token_data["scope"], + received_at=datetime.now()) # Calls the authentication API endpoint to get the token data. # \param access_token: The encoded JWT token. @@ -99,7 +101,8 @@ class AuthorizationHelpers: return UserProfile( user_id = user_data["user_id"], username = user_data["username"], - profile_image_url = user_data.get("profile_image_url", "") + profile_image_url = user_data.get("profile_image_url", ""), + generated_at = datetime.now() ) @staticmethod diff --git a/cura/OAuth2/AuthorizationRequestHandler.py b/cura/OAuth2/AuthorizationRequestHandler.py index 7e0a659a56..193a41305a 100644 --- a/cura/OAuth2/AuthorizationRequestHandler.py +++ b/cura/OAuth2/AuthorizationRequestHandler.py @@ -9,7 +9,6 @@ from cura.OAuth2.Models import AuthenticationResponse, ResponseData, HTTP_STATUS if TYPE_CHECKING: from cura.OAuth2.Models import ResponseStatus - from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers # This handler handles all HTTP requests on the local web server. diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 8ec5232158..011db0011e 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. import json import webbrowser +from datetime import timedelta, datetime from typing import Optional, TYPE_CHECKING from urllib.parse import urlencode import requests.exceptions @@ -51,11 +52,12 @@ class AuthorizationService: # \return UserProfile if a user is logged in, None otherwise. # \sa _parseJWT def getUserProfile(self) -> Optional["UserProfile"]: - try: - self._user_profile = self._parseJWT() - except requests.exceptions.ConnectionError: - # Unable to get connection, can't login. - return None + if not self._user_profile: + try: + self._user_profile = self._parseJWT() + except requests.exceptions.ConnectionError: + # Unable to get connection, can't login. + return None if not self._user_profile and self._auth_data: # If there is still no user profile from the JWT, we have to log in again. @@ -87,10 +89,10 @@ class AuthorizationService: # Get the access token as provided by the response data. def getAccessToken(self) -> Optional[str]: - if not self.getUserProfile(): - # We check if we can get the user profile. - # If we can't get it, that means the access token (JWT) was invalid or expired. - # In that case we try to refresh the access token. + # Check if the current access token is expired and refresh it if that is the case. + creation_date = self._auth_data.received_at or datetime(2000, 1, 1) + expiry_date = creation_date + timedelta(seconds = float(self._auth_data.expires_in)) + if datetime.now() > expiry_date: self.refreshAccessToken() if self._auth_data is None: diff --git a/cura/OAuth2/Models.py b/cura/OAuth2/Models.py index 0515e789e6..818aed64e2 100644 --- a/cura/OAuth2/Models.py +++ b/cura/OAuth2/Models.py @@ -1,6 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - +from datetime import datetime from typing import Optional @@ -38,6 +38,7 @@ class AuthenticationResponse(BaseModel): expires_in = None # type: Optional[str] scope = None # type: Optional[str] err_message = None # type: Optional[str] + received_at = None # type: Optional[datetime] # Response status template.