Fixed OAuthLogin handling code.
BUG=chromium:177357
TEST=login_CryptohomeMounted
Change-Id: I6c88a7499e124bcef339e8b98265066fccd04e7a
Reviewed-on: https://gerrit.chromium.org/gerrit/43694
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: David James <davidjames@chromium.org>
Commit-Queue: Zelidrag Hornung <zelidrag@chromium.org>
Tested-by: Zelidrag Hornung <zelidrag@chromium.org>
diff --git a/client/cros/auth_server.py b/client/cros/auth_server.py
index 9dfe3a4..6908472 100644
--- a/client/cros/auth_server.py
+++ b/client/cros/auth_server.py
@@ -4,7 +4,7 @@
import httplib, json, logging, os, socket, stat, time, urllib
-import common, constants, cryptohome, httpd
+import common, cgi, constants, cryptohome, httpd
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
@@ -26,6 +26,7 @@
sid = '1234'
lsid = '5678'
token = 'aaaa'
+ uber_token = 'bbbb'
__service_login_html = """
<HTML>
@@ -70,6 +71,9 @@
__issue_auth_token_miss_count = 0
__token_auth_miss_count = 0
+ __oauth_login_uber_token_type = 'uber_token'
+ __oauth_login_gaia_type = 'gaia_credentials'
+
def __init__(self,
cert_path='/etc/fake_root_ca/mock_server.pem',
@@ -87,8 +91,10 @@
self._oauth1_get_access_token = constants.OAUTH1_GET_ACCESS_TOKEN_URL
self._oauth1_get_access_token_new = \
constants.OAUTH1_GET_ACCESS_TOKEN_NEW_URL
- self._oauth1_login = constants.OAUTH1_LOGIN_URL
- self._oauth1_login_new = constants.OAUTH1_LOGIN_NEW_URL
+ self._oauth_login = constants.OAUTH_LOGIN_URL
+ self._oauth_login_new = constants.OAUTH_LOGIN_NEW_URL
+
+ self._merge_session = constants.MERGE_SESSION_URL
self._oauth2_wrap_bridge = constants.OAUTH2_WRAP_BRIDGE_URL
self._oauth2_wrap_bridge_new = constants.OAUTH2_WRAP_BRIDGE_NEW_URL
@@ -134,10 +140,12 @@
self._testServer.add_url_handler(
self._oauth1_get_access_token_new,
self._oauth1_get_access_token_responder)
- self._testServer.add_url_handler(self._oauth1_login,
- self._oauth1_login_responder)
- self._testServer.add_url_handler(self._oauth1_login_new,
- self._oauth1_login_responder)
+ self._testServer.add_url_handler(self._oauth_login,
+ self._oauth_login_responder)
+ self._testServer.add_url_handler(self._oauth_login_new,
+ self._oauth_login_responder)
+ self._testServer.add_url_handler(self._merge_session,
+ self._merge_session_responder)
self._testServer.add_url_handler(self._oauth2_wrap_bridge,
self._oauth2_wrap_bridge_responder)
@@ -234,6 +242,25 @@
return True
+ def _ensure_params_set_provided(self, handler, url_args, params_collection):
+ """Verifies alternative sets of URL parameters. Returns name of
+ the first collection from params_collection that is satisfied by
+ url_args. In case when no collection is fully covered by url_args, it
+ will return an empty string.
+ """
+ result = ""
+ for params_set in params_collection:
+ result = params_set['name']
+ for param in params_set['params']:
+ if param not in url_args:
+ result = ""
+ break
+
+ if len(result) != 0:
+ break
+
+ return result
+
def _ensure_params_provided(self, handler, url_args, params):
for param in params:
if not param in url_args:
@@ -293,6 +320,45 @@
handler.end_headers()
+ def _ensure_oauth_login_params_valid(self,
+ handler,
+ url_args):
+ """Checks URL parameters and header values for /OAuthLogin call.
+ """
+ # There are two different OAuthLogin calls - we could be either
+ # fetching GAIA uber token or SID/LSID. The former case is
+ # identified with url argument issueuberauth=1.
+ params_set_name = self._ensure_params_set_provided(
+ handler,
+ url_args,
+ [{'name': self.__oauth_login_uber_token_type,
+ 'params': ['source',
+ 'issueuberauth']},
+ {'name': self.__oauth_login_gaia_type,
+ 'params': ['source']}])
+
+ if len(params_set_name) == 0:
+ raise error.TestError(
+ '%s called with incorrect arguments - %s' %
+ (handler.path, url_args))
+
+ if params_set_name == self.__oauth_login_uber_token_type:
+ if '1' != _value(url_args['issueuberauth']):
+ raise error.TestError(
+ '%s called with incorrect issueuberauth value.' %
+ handler.path)
+
+ oauth_headers = ('Bearer %s' % self.__oauth2_access_token,
+ 'OAuth %s' % self.__oauth2_access_token)
+ # Check OAuth2 access token value.
+ if handler.headers['Authorization'] not in oauth_headers:
+ raise error.TestError(
+ '%s request has wrong "Authorization" header value of %r' %
+ (handler.path, handler.headers['Authorization']))
+
+ return params_set_name
+
+
def _ensure_oauth1_params_valid(self, handler, url_args, expected_token):
self._ensure_params_provided(handler,
url_args,
@@ -321,18 +387,51 @@
'oauth_token_secret': self.__oauth1_access_token_secret}))
- def _oauth1_login_responder(self, handler, url_args):
+ def _oauth_login_responder(self, handler, url_args):
+ """Responder for /OAuthLogin call.
+
+ This call can either return SID+LSID values used for other GAIA API
+ calls or mint GAIA uber token.
+ """
self._log(handler, url_args)
- self._ensure_oauth1_params_valid(handler,
- url_args,
- self.__oauth1_access_token)
+ request_type = self._ensure_oauth_login_params_valid(handler,
+ url_args)
handler.send_response(httplib.OK)
handler.end_headers()
- handler.wfile.write('SID=%s\n' % self.sid)
- handler.wfile.write('LSID=%s\n' % self.lsid)
- handler.wfile.write('Auth=%s\n' % self.token)
+ if request_type == self.__oauth_login_uber_token_type:
+ handler.wfile.write('%s' % self.uber_token)
+ else:
+ handler.wfile.write('SID=%s\n' % self.sid)
+ handler.wfile.write('LSID=%s\n' % self.lsid)
+ handler.wfile.write('Auth=%s\n' % self.token)
+ def _merge_session_responder(self, handler, url_args):
+ """Responder for /MergeSession call.
+
+ This call is suppose to populate cookie jar with SID+LSID cookies
+ minted out of GAIA uber token.
+ """
+ self._log(handler, url_args)
+ self._ensure_params_provided(handler,
+ url_args,
+ ['uberauth',
+ 'continue',
+ 'source'])
+ if self.uber_token != _value(url_args['uberauth']):
+ raise error.TestError(
+ '%s has invalid uberauth value of "%s"' %
+ (handler.path, _value(url_args['uberauth'])))
+
+ handler.send_response(httplib.OK)
+ handler.send_header('Set-Cookie',
+ 'SID=%s; Path=/; Secure; HttpOnly' %
+ self.sid)
+ handler.send_header('Set-Cookie',
+ 'LSID=%s; Path=/; Secure; HttpOnly' %
+ self.lsid)
+ handler.end_headers()
+
def _oauth2_wrap_bridge_responder(self, handler, url_args):
self._log(handler, url_args)
self._ensure_oauth1_params_valid(handler,
diff --git a/client/cros/constants.py b/client/cros/constants.py
index eff1402..0014526 100644
--- a/client/cros/constants.py
+++ b/client/cros/constants.py
@@ -83,8 +83,9 @@
OAUTH1_GET_REQUEST_TOKEN_NEW_URL = '/o/oauth/GetOAuthToken/'
OAUTH1_GET_ACCESS_TOKEN_URL = '/accounts/OAuthGetAccessToken'
OAUTH1_GET_ACCESS_TOKEN_NEW_URL = '/OAuthGetAccessToken'
-OAUTH1_LOGIN_URL = '/accounts/OAuthLogin'
-OAUTH1_LOGIN_NEW_URL = '/OAuthLogin'
+OAUTH_LOGIN_URL = '/accounts/OAuthLogin'
+OAUTH_LOGIN_NEW_URL = '/OAuthLogin'
+MERGE_SESSION_URL = '/MergeSession'
OAUTH2_CLIENT_ID = '77185425430.apps.googleusercontent.com'
OAUTH2_CLIENT_SECRET = 'OTJgUOQcT7lO7GsGZq2G4IlT'