depot_tools: Remove depot-tools-auth

Users must use luci-auth now.

Bug: 1001756
Change-Id: I04cab6bdbfbd958f386a4cab761dfe4d34073afc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1849810
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: Anthony Polito <apolito@google.com>
diff --git a/auth.py b/auth.py
index 0da997c..f717be1 100644
--- a/auth.py
+++ b/auth.py
@@ -50,13 +50,6 @@
 # Deprecated. Use OAUTH_SCOPE_EMAIL instead.
 OAUTH_SCOPES = OAUTH_SCOPE_EMAIL
 
-# Path to a file with cached OAuth2 credentials used by default relative to the
-# home dir (see _get_token_cache_path). It should be a safe location accessible
-# only to a current user: knowing content of this file is roughly equivalent to
-# knowing account password. Single file can hold multiple independent tokens
-# identified by token_cache_key (see Authenticator).
-OAUTH_TOKENS_CACHE = '.depot_tools_oauth2_tokens'
-
 
 # Authentication configuration extracted from command line options.
 # See doc string for 'make_auth_config' for meaning of fields.
@@ -381,79 +374,38 @@
   return opts
 
 
-def get_authenticator_for_host(hostname, config, scopes=OAUTH_SCOPE_EMAIL):
+def get_authenticator(config, scopes=OAUTH_SCOPE_EMAIL):
   """Returns Authenticator instance to access given host.
 
   Args:
-    hostname: a naked hostname or http(s)://<hostname>[/] URL. Used to derive
-        a cache key for token cache.
     config: AuthConfig instance.
     scopes: space separated oauth scopes. Defaults to OAUTH_SCOPE_EMAIL.
 
   Returns:
     Authenticator object.
-
-  Raises:
-    AuthenticationError if hostname is invalid.
   """
-  hostname = hostname.lower().rstrip('/')
-  # Append some scheme, otherwise urlparse puts hostname into parsed.path.
-  if '://' not in hostname:
-    hostname = 'https://' + hostname
-  parsed = urlparse.urlparse(hostname)
-
-  if parsed.path or parsed.params or parsed.query or parsed.fragment:
-    raise AuthenticationError(
-        'Expecting a hostname or root host URL, got %s instead' % hostname)
-  return Authenticator(parsed.netloc, config, scopes)
+  return Authenticator(config, scopes)
 
 
 class Authenticator(object):
   """Object that knows how to refresh access tokens when needed.
 
   Args:
-    token_cache_key: string key of a section of the token cache file to use
-        to keep the tokens. See hostname_to_token_cache_key.
     config: AuthConfig object that holds authentication configuration.
   """
 
-  def __init__(self, token_cache_key, config, scopes):
+  def __init__(self, config, scopes):
     assert isinstance(config, AuthConfig)
     assert config.use_oauth2
     self._access_token = None
     self._config = config
     self._lock = threading.Lock()
-    self._token_cache_key = token_cache_key
     self._external_token = None
     self._scopes = scopes
     if config.refresh_token_json:
       self._external_token = _read_refresh_token_json(config.refresh_token_json)
     logging.debug('Using auth config %r', config)
 
-  def login(self):
-    """Performs interactive login flow if necessary.
-
-    Raises:
-      AuthenticationError on error or if interrupted.
-    """
-    if self._external_token:
-      raise AuthenticationError(
-          'Can\'t run login flow when using --auth-refresh-token-json.')
-    return self.get_access_token(
-        force_refresh=True, allow_user_interaction=True)
-
-  def logout(self):
-    """Revokes the refresh token and deletes it from the cache.
-
-    Returns True if had some credentials cached.
-    """
-    with self._lock:
-      self._access_token = None
-      had_creds = bool(_get_luci_auth_credentials(self._scopes))
-      subprocess2.check_call(
-          ['luci-auth', 'logout', '-scopes', self._scopes])
-    return had_creds
-
   def has_cached_credentials(self):
     """Returns True if long term credentials (refresh token) are in cache.
 
@@ -526,16 +478,6 @@
 
       return self._access_token
 
-  def get_token_info(self):
-    """Returns a result of /oauth2/v2/tokeninfo call with token info."""
-    access_token = self.get_access_token()
-    resp, content = httplib2.Http().request(
-        uri='https://www.googleapis.com/oauth2/v2/tokeninfo?%s' % (
-            urllib.urlencode({'access_token': access_token.token})))
-    if resp.status == 200:
-      return json.loads(content)
-    raise AuthenticationError('Failed to fetch the token info: %r' % content)
-
   def authorize(self, http):
     """Monkey patches authentication logic of httplib2.Http instance.
 
@@ -684,20 +626,6 @@
 ## Private functions.
 
 
-def _get_token_cache_path():
-  # On non Win just use HOME.
-  if sys.platform != 'win32':
-    return os.path.join(os.path.expanduser('~'), OAUTH_TOKENS_CACHE)
-  # Prefer USERPROFILE over HOME, since HOME is overridden in
-  # git-..._bin/cmd/git.cmd to point to depot_tools. depot-tools-auth.py script
-  # (and all other scripts) doesn't use this override and thus uses another
-  # value for HOME. git.cmd doesn't touch USERPROFILE though, and usually
-  # USERPROFILE == HOME on Windows.
-  if 'USERPROFILE' in os.environ:
-    return os.path.join(os.environ['USERPROFILE'], OAUTH_TOKENS_CACHE)
-  return os.path.join(os.path.expanduser('~'), OAUTH_TOKENS_CACHE)
-
-
 def _is_headless():
   """True if machine doesn't seem to have a display."""
   return sys.platform == 'linux2' and not os.environ.get('DISPLAY')
@@ -750,6 +678,7 @@
       user_agent=None,
       revoke_uri=None)
 
+
 def _run_oauth_dance(scopes):
   """Perform full 3-legged OAuth2 flow with the browser.
 
diff --git a/depot-tools-auth b/depot-tools-auth
deleted file mode 100755
index 9233c92..0000000
--- a/depot-tools-auth
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-base_dir=$(dirname "$0")
-
-PYTHONDONTWRITEBYTECODE=1 exec python "$base_dir/depot-tools-auth.py" "$@"
diff --git a/depot-tools-auth.bat b/depot-tools-auth.bat
deleted file mode 100644
index 37280b7..0000000
--- a/depot-tools-auth.bat
+++ /dev/null
@@ -1,12 +0,0 @@
-@echo off

-:: Copyright 2015 The Chromium Authors. All rights reserved.

-:: Use of this source code is governed by a BSD-style license that can be

-:: found in the LICENSE file.

-setlocal

-

-:: Ensure that "depot_tools" is somewhere in PATH so this tool can be used

-:: standalone, but allow other PATH manipulations to take priority.

-set PATH=%PATH%;%~dp0

-

-:: Defer control.

-python "%~dp0\depot-tools-auth.py" %*

diff --git a/depot-tools-auth.py b/depot-tools-auth.py
deleted file mode 100755
index 17be1e4..0000000
--- a/depot-tools-auth.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Manages cached OAuth2 tokens used by other depot_tools scripts.
-
-Usage:
-  depot-tools-auth login codereview.chromium.org
-  depot-tools-auth info codereview.chromium.org
-  depot-tools-auth logout codereview.chromium.org
-"""
-
-from __future__ import print_function
-
-import logging
-import optparse
-import sys
-import os
-
-import auth
-import setup_color
-import subcommand
-
-__version__ = '1.0'
-
-
-@subcommand.usage('<hostname>')
-def CMDlogin(parser, args):
-  """Performs interactive login and caches authentication token."""
-  # Forcefully relogin, revoking previous token.
-  hostname, authenticator = parser.parse_args(args)
-  authenticator.logout()
-  authenticator.login()
-  print_token_info(hostname, authenticator)
-  return 0
-
-
-@subcommand.usage('<hostname>')
-def CMDlogout(parser, args):
-  """Revokes cached authentication token and removes it from disk."""
-  _, authenticator = parser.parse_args(args)
-  done = authenticator.logout()
-  print('Done.' if done else 'Already logged out.')
-  return 0
-
-
-@subcommand.usage('<hostname>')
-def CMDinfo(parser, args):
-  """Shows email associated with a cached authentication token."""
-  # If no token is cached, AuthenticationError will be caught in 'main'.
-  hostname, authenticator = parser.parse_args(args)
-  print_token_info(hostname, authenticator)
-  return 0
-
-
-def print_token_info(hostname, authenticator):
-  token_info = authenticator.get_token_info()
-  print('Logged in to %s as %s.' % (hostname, token_info['email']))
-  print('')
-  print('To login with a different email run:')
-  print('  depot-tools-auth login %s' % hostname)
-  print('To logout and purge the authentication token run:')
-  print('  depot-tools-auth logout %s' % hostname)
-
-
-class OptionParser(optparse.OptionParser):
-  def __init__(self, *args, **kwargs):
-    optparse.OptionParser.__init__(
-        self, *args, prog='depot-tools-auth', version=__version__, **kwargs)
-    self.add_option(
-        '-v', '--verbose', action='count', default=0,
-        help='Use 2 times for more debugging info')
-    auth.add_auth_options(self, auth.make_auth_config(use_oauth2=True))
-
-  def parse_args(self, args=None, values=None):
-    """Parses options and returns (hostname, auth.Authenticator object)."""
-    options, args = optparse.OptionParser.parse_args(self, args, values)
-    levels = [logging.WARNING, logging.INFO, logging.DEBUG]
-    logging.basicConfig(level=levels[min(options.verbose, len(levels) - 1)])
-    auth_config = auth.extract_auth_config_from_options(options)
-    if len(args) != 1:
-      self.error('Expecting single argument (hostname).')
-    if not auth_config.use_oauth2:
-      self.error('This command is only usable with OAuth2 authentication')
-    return args[0], auth.get_authenticator_for_host(args[0], auth_config)
-
-
-def main(argv):
-  dispatcher = subcommand.CommandDispatcher(__name__)
-  try:
-    return dispatcher.execute(OptionParser(), argv)
-  except auth.AuthenticationError as e:
-    print(e, file=sys.stderr)
-    return 1
-
-
-if __name__ == '__main__':
-  setup_color.init()
-  try:
-    sys.exit(main(sys.argv[1:]))
-  except KeyboardInterrupt:
-    sys.stderr.write('interrupted\n')
-    sys.exit(1)
diff --git a/git_cl.py b/git_cl.py
index 0b1d915..ff6d5b3 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -465,11 +465,7 @@
   if not requests:
     return
 
-  codereview_url = changelist.GetCodereviewServer()
-  codereview_host = urlparse.urlparse(codereview_url).hostname
-
-  authenticator = auth.get_authenticator_for_host(codereview_host, auth_config)
-  http = authenticator.authorize(httplib2.Http())
+  http = auth.get_authenticator(auth_config).authorize(httplib2.Http())
   http.force_exception_to_status_code = True
 
   batch_request = {'requests': requests}
@@ -544,10 +540,7 @@
       'fields': ','.join('builds.*.' + field for field in fields),
   }
 
-  codereview_url = changelist.GetCodereviewServer()
-  codereview_host = urlparse.urlparse(codereview_url).hostname
-
-  authenticator = auth.get_authenticator_for_host(codereview_host, auth_config)
+  authenticator = auth.get_authenticator(auth_config)
   if authenticator.has_cached_credentials():
     http = authenticator.authorize(httplib2.Http())
   else:
diff --git a/my_activity.py b/my_activity.py
index 5e76cc1..81b901d 100755
--- a/my_activity.py
+++ b/my_activity.py
@@ -293,8 +293,7 @@
 
   def monorail_get_auth_http(self):
     auth_config = auth.extract_auth_config_from_options(self.options)
-    authenticator = auth.get_authenticator_for_host(
-        'bugs.chromium.org', auth_config)
+    authenticator = auth.get_authenticator(auth_config)
     # Manually use a long timeout (10m); for some users who have a
     # long history on the issue tracker, whatever the default timeout
     # is is reached.
diff --git a/presubmit_canned_checks.py b/presubmit_canned_checks.py
index 4cd3a84..2b559af 100644
--- a/presubmit_canned_checks.py
+++ b/presubmit_canned_checks.py
@@ -1417,8 +1417,7 @@
 
   # authentication
   try:
-    authenticator = auth.get_authenticator_for_host(
-        LUCI_CONFIG_HOST_NAME, auth.make_auth_config())
+    authenticator = auth.get_authenticator(auth.make_auth_config())
     acc_tkn = authenticator.get_access_token()
   except auth.AuthenticationError as e:
     return [output_api.PresubmitError(
diff --git a/tests/git_cl_test.py b/tests/git_cl_test.py
index 1a2612f..917024a 100755
--- a/tests/git_cl_test.py
+++ b/tests/git_cl_test.py
@@ -636,7 +636,7 @@
               self._mocked_call('write_json', path, contents))
     self.mock(git_cl.presubmit_support, 'DoPresubmitChecks', PresubmitMock)
     self.mock(git_cl.watchlists, 'Watchlists', WatchlistsMock)
-    self.mock(git_cl.auth, 'get_authenticator_for_host', AuthenticatorMock)
+    self.mock(git_cl.auth, 'get_authenticator', AuthenticatorMock)
     self.mock(git_cl.gerrit_util, 'GetChangeDetail',
               lambda *args, **kwargs: self._mocked_call(
                   'GetChangeDetail', *args, **kwargs))
@@ -3021,7 +3021,8 @@
                return_value='https://chromium-review.googlesource.com').start()
     mock.patch('git_cl.Changelist.GetMostRecentPatchset',
                return_value=7).start()
-    mock.patch('git_cl.auth.get_authenticator_for_host', AuthenticatorMock())
+    mock.patch('git_cl.auth.get_authenticator',
+               return_value=AuthenticatorMock()).start()
     mock.patch('git_cl.Changelist._GetChangeDetail',
                return_value=self._CHANGE_DETAIL).start()
     mock.patch('git_cl._call_buildbucket',
diff --git a/tests/presubmit_unittest.py b/tests/presubmit_unittest.py
index 8c476db..af7acd3 100755
--- a/tests/presubmit_unittest.py
+++ b/tests/presubmit_unittest.py
@@ -1642,8 +1642,8 @@
                      presubmit.OutputApi.PresubmitPromptWarning)
 
   @mock.patch('git_cl.Changelist')
-  @mock.patch('auth.get_authenticator_for_host')
-  def testCannedCheckChangedLUCIConfigs(self, mockGAFH, mockChangelist):
+  @mock.patch('auth.get_authenticator')
+  def testCannedCheckChangedLUCIConfigs(self, mockGetAuth, mockChangelist):
     affected_file1 = mock.MagicMock(presubmit.GitAffectedFile)
     affected_file1.LocalPath.return_value = 'foo.cfg'
     affected_file1.NewContents.return_value = ['test', 'foo']
@@ -1651,7 +1651,7 @@
     affected_file2.LocalPath.return_value = 'bar.cfg'
     affected_file2.NewContents.return_value = ['test', 'bar']
 
-    mockGAFH().get_access_token().token = 123
+    mockGetAuth().get_access_token().token = 123
 
     host = 'https://host.com'
     branch = 'branch'