From 3fd55f9520cada39a7277ad5a184526abdd30549 Mon Sep 17 00:00:00 2001 From: "pgervais@chromium.org" Date: Fri, 18 Apr 2014 22:17:21 +0000 Subject: [PATCH] Automatically reauthenticate to Rietveld Added automatic detection of OAuth2 token expiracy. Token is automatically renewed when necessary. BUG=363825 Review URL: https://codereview.chromium.org/243323003 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@264871 0039d316-1c4b-4281-b951-d872f2087c98 --- rietveld.py | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/rietveld.py b/rietveld.py index 97dae6d08..d78c0171d 100644 --- a/rietveld.py +++ b/rietveld.py @@ -481,14 +481,14 @@ class OAuthRpcServer(object): "OAuth2 support requires it.") logging.error("Installing pyopenssl will probably solve this issue.") raise RuntimeError('No OpenSSL support') - creds = oa2client.SignedJwtAssertionCredentials( + self.creds = oa2client.SignedJwtAssertionCredentials( client_email, client_private_key, 'https://www.googleapis.com/auth/userinfo.email', private_key_password=private_key_password, user_agent=user_agent) - self._http = creds.authorize(httplib2.Http(timeout=timeout)) + self._http = self.creds.authorize(httplib2.Http(timeout=timeout)) def Send(self, request_path, @@ -525,17 +525,30 @@ class OAuthRpcServer(object): if kwargs: url += "?" + urllib.urlencode(kwargs) - ret = self._http.request(url, - method=method, - body=payload, - headers=headers) - - if (method == 'GET' - and not ret[0]['content-location'].startswith(self.host)): - upload.logging.warning('Redirection to host %s detected: ' - 'login may have failed/expired.' - % urlparse.urlparse( - ret[0]['content-location']).netloc) + # This weird loop is there to detect when the OAuth2 token has expired. + # This is specific to appengine *and* rietveld. It relies on the + # assumption that a 302 is triggered only by an expired OAuth2 token. This + # prevents any usage of redirections in pages accessed this way. + + # This variable is used to make sure the following loop runs only twice. + redirect_caught = False + while True: + try: + ret = self._http.request(url, + method=method, + body=payload, + headers=headers, + redirections=0) + except httplib2.RedirectLimit: + if redirect_caught or method != 'GET': + logging.error('Redirection detected after logging in. Giving up.') + raise + redirect_caught = True + logging.debug('Redirection detected. Trying to log in again...') + self.creds.access_token = None + continue + break + return ret[1] finally: