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'