fix!: drop support for Python 2.7 (#778)

Drop use of 'six' wrapper library.

Drop 'u"' prefixes.

Drop support for app_engine 'classic' mode (Python 2.7-only).

Release-As: 2.0.0b1

Closes #777.
diff --git a/google/auth/_cloud_sdk.py b/google/auth/_cloud_sdk.py
index 40e6aec..1f13ad4 100644
--- a/google/auth/_cloud_sdk.py
+++ b/google/auth/_cloud_sdk.py
@@ -18,8 +18,6 @@
 import os
 import subprocess
 
-import six
-
 from google.auth import environment_vars
 from google.auth import exceptions
 
@@ -156,4 +154,4 @@
         new_exc = exceptions.UserAccessTokenError(
             "Failed to obtain access token", caught_exc
         )
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
diff --git a/google/auth/_credentials_async.py b/google/auth/_credentials_async.py
index d4d4e2c..760758d 100644
--- a/google/auth/_credentials_async.py
+++ b/google/auth/_credentials_async.py
@@ -18,13 +18,10 @@
 import abc
 import inspect
 
-import six
-
 from google.auth import credentials
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Credentials(credentials.Credentials):
+class Credentials(credentials.Credentials, metaclass=abc.ABCMeta):
     """Async inherited credentials class from google.auth.credentials.
     The added functionality is the before_request call which requires
     async/await syntax.
@@ -84,8 +81,7 @@
     """
 
 
-@six.add_metaclass(abc.ABCMeta)
-class ReadOnlyScoped(credentials.ReadOnlyScoped):
+class ReadOnlyScoped(credentials.ReadOnlyScoped, metaclass=abc.ABCMeta):
     """Interface for credentials whose scopes can be queried.
 
     OAuth 2.0-based credentials allow limiting access using scopes as described
@@ -171,6 +167,5 @@
         return credentials
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Signing(credentials.Signing):
+class Signing(credentials.Signing, metaclass=abc.ABCMeta):
     """Interface for credentials that can cryptographically sign messages."""
diff --git a/google/auth/_default.py b/google/auth/_default.py
index f7e308f..7da77a2 100644
--- a/google/auth/_default.py
+++ b/google/auth/_default.py
@@ -23,8 +23,6 @@
 import os
 import warnings
 
-import six
-
 from google.auth import environment_vars
 from google.auth import exceptions
 import google.auth.transport._http_client
@@ -115,7 +113,7 @@
             new_exc = exceptions.DefaultCredentialsError(
                 "File {} is not a valid json file.".format(filename), caught_exc
             )
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
     # The type key should indicate that the file is either a service account
     # credentials file or an authorized user credentials file.
@@ -131,7 +129,7 @@
         except ValueError as caught_exc:
             msg = "Failed to load authorized user credentials from {}".format(filename)
             new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
         if quota_project_id:
             credentials = credentials.with_quota_project(quota_project_id)
         if not credentials.quota_project_id:
@@ -148,7 +146,7 @@
         except ValueError as caught_exc:
             msg = "Failed to load service account credentials from {}".format(filename)
             new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
         if quota_project_id:
             credentials = credentials.with_quota_project(quota_project_id)
         return credentials, info.get("project_id")
diff --git a/google/auth/_default_async.py b/google/auth/_default_async.py
index d12a642..82e6c43 100644
--- a/google/auth/_default_async.py
+++ b/google/auth/_default_async.py
@@ -21,8 +21,6 @@
 import json
 import os
 
-import six
-
 from google.auth import _default
 from google.auth import environment_vars
 from google.auth import exceptions
@@ -63,7 +61,7 @@
             new_exc = exceptions.DefaultCredentialsError(
                 "File {} is not a valid json file.".format(filename), caught_exc
             )
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
     # The type key should indicate that the file is either a service account
     # credentials file or an authorized user credentials file.
@@ -79,7 +77,7 @@
         except ValueError as caught_exc:
             msg = "Failed to load authorized user credentials from {}".format(filename)
             new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
         if not credentials.quota_project_id:
             _default._warn_about_problematic_credentials(credentials)
         return credentials, None
@@ -94,7 +92,7 @@
         except ValueError as caught_exc:
             msg = "Failed to load service account credentials from {}".format(filename)
             new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
         return credentials, info.get("project_id")
 
     else:
diff --git a/google/auth/_helpers.py b/google/auth/_helpers.py
index 21c987a..09f32f8 100644
--- a/google/auth/_helpers.py
+++ b/google/auth/_helpers.py
@@ -17,9 +17,7 @@
 import base64
 import calendar
 import datetime
-
-import six
-from six.moves import urllib
+import urllib
 
 
 CLOCK_SKEW_SECS = 10  # 10 seconds
@@ -84,9 +82,6 @@
 def to_bytes(value, encoding="utf-8"):
     """Converts a string value to bytes, if necessary.
 
-    Unfortunately, ``six.b`` is insufficient for this task since in
-    Python 2 because it does not modify ``unicode`` objects.
-
     Args:
         value (Union[str, bytes]): The value to be converted.
         encoding (str): The encoding to use to convert unicode to bytes.
@@ -99,8 +94,8 @@
     Raises:
         ValueError: If the value could not be converted to bytes.
     """
-    result = value.encode(encoding) if isinstance(value, six.text_type) else value
-    if isinstance(result, six.binary_type):
+    result = value.encode(encoding) if isinstance(value, str) else value
+    if isinstance(result, bytes):
         return result
     else:
         raise ValueError("{0!r} could not be converted to bytes".format(value))
@@ -119,8 +114,8 @@
     Raises:
         ValueError: If the value could not be converted to unicode.
     """
-    result = value.decode("utf-8") if isinstance(value, six.binary_type) else value
-    if isinstance(result, six.text_type):
+    result = value.decode("utf-8") if isinstance(value, bytes) else value
+    if isinstance(result, str):
         return result
     else:
         raise ValueError("{0!r} could not be converted to unicode".format(value))
@@ -162,7 +157,7 @@
     query_params.update(params)
     # Remove any values specified in remove.
     query_params = {
-        key: value for key, value in six.iteritems(query_params) if key not in remove
+        key: value for key, value in query_params.items() if key not in remove
     }
     # Re-encoded the query string.
     new_query = urllib.parse.urlencode(query_params, doseq=True)
diff --git a/google/auth/_oauth2client.py b/google/auth/_oauth2client.py
index 95a9876..3512e1d 100644
--- a/google/auth/_oauth2client.py
+++ b/google/auth/_oauth2client.py
@@ -21,8 +21,6 @@
 
 from __future__ import absolute_import
 
-import six
-
 from google.auth import _helpers
 import google.auth.app_engine
 import google.auth.compute_engine
@@ -34,7 +32,7 @@
     import oauth2client.contrib.gce
     import oauth2client.service_account
 except ImportError as caught_exc:
-    six.raise_from(ImportError("oauth2client is not installed."), caught_exc)
+    raise ImportError("oauth2client is not installed.") from caught_exc
 
 try:
     import oauth2client.contrib.appengine  # pytype: disable=import-error
@@ -166,4 +164,4 @@
         return _CLASS_CONVERSION_MAP[credentials_class](credentials)
     except KeyError as caught_exc:
         new_exc = ValueError(_CONVERT_ERROR_TMPL.format(credentials_class))
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
diff --git a/google/auth/_service_account_info.py b/google/auth/_service_account_info.py
index 3d340c7..54a40e9 100644
--- a/google/auth/_service_account_info.py
+++ b/google/auth/_service_account_info.py
@@ -17,8 +17,6 @@
 import io
 import json
 
-import six
-
 from google.auth import crypt
 
 
@@ -43,7 +41,7 @@
     """
     keys_needed = set(require if require is not None else [])
 
-    missing = keys_needed.difference(six.iterkeys(data))
+    missing = keys_needed.difference(data)
 
     if missing:
         raise ValueError(
diff --git a/google/auth/aws.py b/google/auth/aws.py
index c2b521c..2f2a135 100644
--- a/google/auth/aws.py
+++ b/google/auth/aws.py
@@ -39,13 +39,12 @@
 
 import hashlib
 import hmac
+import http.client
 import io
 import json
 import os
 import re
-
-from six.moves import http_client
-from six.moves import urllib
+import urllib
 
 from google.auth import _helpers
 from google.auth import environment_vars
@@ -627,7 +626,7 @@
             else response.data
         )
 
-        if response.status != http_client.OK:
+        if response.status != http.client.OK:
             raise exceptions.RefreshError(
                 "Unable to retrieve AWS security credentials", response_body
             )
@@ -666,7 +665,7 @@
             else response.data
         )
 
-        if response.status != http_client.OK:
+        if response.status != http.client.OK:
             raise exceptions.RefreshError(
                 "Unable to retrieve AWS role name", response_body
             )
diff --git a/google/auth/compute_engine/_metadata.py b/google/auth/compute_engine/_metadata.py
index 5687a42..ee6fec6 100644
--- a/google/auth/compute_engine/_metadata.py
+++ b/google/auth/compute_engine/_metadata.py
@@ -18,13 +18,11 @@
 """
 
 import datetime
+import http.client
 import json
 import logging
 import os
-
-import six
-from six.moves import http_client
-from six.moves.urllib import parse as urlparse
+from urllib import parse as urlparse
 
 from google.auth import _helpers
 from google.auth import environment_vars
@@ -91,7 +89,7 @@
 
             metadata_flavor = response.headers.get(_METADATA_FLAVOR_HEADER)
             return (
-                response.status == http_client.OK
+                response.status == http.client.OK
                 and metadata_flavor == _METADATA_FLAVOR_VALUE
             )
 
@@ -165,7 +163,7 @@
             "metadata service. Compute Engine Metadata server unavailable".format(url)
         )
 
-    if response.status == http_client.OK:
+    if response.status == http.client.OK:
         content = _helpers.from_bytes(response.data)
         if response.headers["content-type"] == "application/json":
             try:
@@ -175,7 +173,7 @@
                     "Received invalid JSON from the Google Compute Engine"
                     "metadata service: {:.20}".format(content)
                 )
-                six.raise_from(new_exc, caught_exc)
+                raise new_exc from caught_exc
         else:
             return content
     else:
diff --git a/google/auth/compute_engine/credentials.py b/google/auth/compute_engine/credentials.py
index 1671656..cb4e0f0 100644
--- a/google/auth/compute_engine/credentials.py
+++ b/google/auth/compute_engine/credentials.py
@@ -21,8 +21,6 @@
 
 import datetime
 
-import six
-
 from google.auth import _helpers
 from google.auth import credentials
 from google.auth import exceptions
@@ -38,7 +36,7 @@
     These credentials use the Google Compute Engine metadata server to obtain
     OAuth 2.0 access tokens associated with the instance's service account,
     and are also used for Cloud Run, Flex and App Engine (except for the Python
-    2.7 runtime).
+    2.7 runtime, which is supported only on older versions of this library).
 
     For more information about Compute Engine authentication, including how
     to configure scopes, see the `Compute Engine authentication
@@ -114,7 +112,7 @@
             )
         except exceptions.TransportError as caught_exc:
             new_exc = exceptions.RefreshError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
     @property
     def service_account_email(self):
@@ -352,7 +350,7 @@
             id_token = _metadata.get(request, path, params=params)
         except exceptions.TransportError as caught_exc:
             new_exc = exceptions.RefreshError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         _, payload, _, _ = jwt._unverified_decode(id_token)
         return id_token, datetime.datetime.fromtimestamp(payload["exp"])
diff --git a/google/auth/credentials.py b/google/auth/credentials.py
index 7d3c798..6356f54 100644
--- a/google/auth/credentials.py
+++ b/google/auth/credentials.py
@@ -17,13 +17,10 @@
 
 import abc
 
-import six
-
 from google.auth import _helpers
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Credentials(object):
+class Credentials(object, metaclass=abc.ABCMeta):
     """Base class for all credentials.
 
     All credentials have a :attr:`token` that is used for authentication and
@@ -187,8 +184,7 @@
         """Anonymous credentials do nothing to the request."""
 
 
-@six.add_metaclass(abc.ABCMeta)
-class ReadOnlyScoped(object):
+class ReadOnlyScoped(object, metaclass=abc.ABCMeta):
     """Interface for credentials whose scopes can be queried.
 
     OAuth 2.0-based credentials allow limiting access using scopes as described
@@ -329,8 +325,7 @@
         return credentials
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Signing(object):
+class Signing(object, metaclass=abc.ABCMeta):
     """Interface for credentials that can cryptographically sign messages."""
 
     @abc.abstractmethod
diff --git a/google/auth/crypt/__init__.py b/google/auth/crypt/__init__.py
index 15ac950..97e9d81 100644
--- a/google/auth/crypt/__init__.py
+++ b/google/auth/crypt/__init__.py
@@ -37,8 +37,6 @@
 version is at least 1.4.0.
 """
 
-import six
-
 from google.auth.crypt import base
 from google.auth.crypt import rsa
 
@@ -90,7 +88,7 @@
     Returns:
         bool: True if the signature is valid, otherwise False.
     """
-    if isinstance(certs, (six.text_type, six.binary_type)):
+    if isinstance(certs, (str, bytes)):
         certs = [certs]
 
     for cert in certs:
diff --git a/google/auth/crypt/_python_rsa.py b/google/auth/crypt/_python_rsa.py
index ec30dd0..1c4a9da 100644
--- a/google/auth/crypt/_python_rsa.py
+++ b/google/auth/crypt/_python_rsa.py
@@ -21,12 +21,13 @@
 
 from __future__ import absolute_import
 
+import io
+
 from pyasn1.codec.der import decoder
 from pyasn1_modules import pem
 from pyasn1_modules.rfc2459 import Certificate
 from pyasn1_modules.rfc5208 import PrivateKeyInfo
 import rsa
-import six
 
 from google.auth import _helpers
 from google.auth.crypt import base
@@ -52,9 +53,9 @@
     """
     num_bits = len(bit_list)
     byte_vals = bytearray()
-    for start in six.moves.xrange(0, num_bits, 8):
+    for start in range(0, num_bits, 8):
         curr_bits = bit_list[start : start + 8]
-        char_val = sum(val * digit for val, digit in six.moves.zip(_POW2, curr_bits))
+        char_val = sum(val * digit for val, digit in zip(_POW2, curr_bits))
         byte_vals.append(char_val)
     return bytes(byte_vals)
 
@@ -152,7 +153,7 @@
         """
         key = _helpers.from_bytes(key)  # PEM expects str in Python 3
         marker_id, key_bytes = pem.readPemBlocksFromFile(
-            six.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER
+            io.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER
         )
 
         # Key is in pkcs1 format.
diff --git a/google/auth/crypt/base.py b/google/auth/crypt/base.py
index c98d5bf..0bda9c3 100644
--- a/google/auth/crypt/base.py
+++ b/google/auth/crypt/base.py
@@ -18,15 +18,12 @@
 import io
 import json
 
-import six
-
 
 _JSON_FILE_PRIVATE_KEY = "private_key"
 _JSON_FILE_PRIVATE_KEY_ID = "private_key_id"
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Verifier(object):
+class Verifier(object, metaclass=abc.ABCMeta):
     """Abstract base class for crytographic signature verifiers."""
 
     @abc.abstractmethod
@@ -46,8 +43,7 @@
         raise NotImplementedError("Verify must be implemented")
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Signer(object):
+class Signer(object, metaclass=abc.ABCMeta):
     """Abstract base class for cryptographic signers."""
 
     @abc.abstractproperty
@@ -70,8 +66,7 @@
         raise NotImplementedError("Sign must be implemented")
 
 
-@six.add_metaclass(abc.ABCMeta)
-class FromServiceAccountMixin(object):
+class FromServiceAccountMixin(object, metaclass=abc.ABCMeta):
     """Mix-in to enable factory constructors for a Signer."""
 
     @abc.abstractmethod
diff --git a/google/auth/external_account.py b/google/auth/external_account.py
index 1f3034a..24b93b4 100644
--- a/google/auth/external_account.py
+++ b/google/auth/external_account.py
@@ -33,8 +33,6 @@
 import json
 import re
 
-import six
-
 from google.auth import _helpers
 from google.auth import credentials
 from google.auth import exceptions
@@ -52,8 +50,9 @@
 _CLOUD_RESOURCE_MANAGER = "https://cloudresourcemanager.googleapis.com/v1/projects/"
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Credentials(credentials.Scoped, credentials.CredentialsWithQuotaProject):
+class Credentials(
+    credentials.Scoped, credentials.CredentialsWithQuotaProject, metaclass=abc.ABCMeta
+):
     """Base class for all external account credentials.
 
     This is used to instantiate Credentials for exchanging external account
diff --git a/google/auth/iam.py b/google/auth/iam.py
index 5d63dc5..277f4b7 100644
--- a/google/auth/iam.py
+++ b/google/auth/iam.py
@@ -20,10 +20,9 @@
 """
 
 import base64
+import http.client
 import json
 
-from six.moves import http_client
-
 from google.auth import _helpers
 from google.auth import crypt
 from google.auth import exceptions
@@ -77,7 +76,7 @@
         self._credentials.before_request(self._request, method, url, headers)
         response = self._request(url=url, method=method, body=body, headers=headers)
 
-        if response.status != http_client.OK:
+        if response.status != http.client.OK:
             raise exceptions.TransportError(
                 "Error calling the IAM signBlob API: {}".format(response.data)
             )
diff --git a/google/auth/identity_pool.py b/google/auth/identity_pool.py
index 5362199..c331e09 100644
--- a/google/auth/identity_pool.py
+++ b/google/auth/identity_pool.py
@@ -33,11 +33,7 @@
 access tokens.
 """
 
-try:
-    from collections.abc import Mapping
-# Python 2.7 compatibility
-except ImportError:  # pragma: NO COVER
-    from collections import Mapping
+from collections.abc import Mapping
 import io
 import json
 import os
diff --git a/google/auth/impersonated_credentials.py b/google/auth/impersonated_credentials.py
index b8a6c49..2704bfd 100644
--- a/google/auth/impersonated_credentials.py
+++ b/google/auth/impersonated_credentials.py
@@ -28,11 +28,9 @@
 import base64
 import copy
 from datetime import datetime
+import http.client
 import json
 
-import six
-from six.moves import http_client
-
 from google.auth import _helpers
 from google.auth import credentials
 from google.auth import exceptions
@@ -100,7 +98,7 @@
         else response.data
     )
 
-    if response.status != http_client.OK:
+    if response.status != http.client.OK:
         exceptions.RefreshError(_REFRESH_ERROR, response_body)
 
     try:
@@ -117,7 +115,7 @@
             ),
             response_body,
         )
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
 
 class Credentials(credentials.CredentialsWithQuotaProject, credentials.Signing):
diff --git a/google/auth/jwt.py b/google/auth/jwt.py
index e9f4f69..d931bf7 100644
--- a/google/auth/jwt.py
+++ b/google/auth/jwt.py
@@ -40,18 +40,13 @@
 
 """
 
-try:
-    from collections.abc import Mapping
-# Python 2.7 compatibility
-except ImportError:  # pragma: NO COVER
-    from collections import Mapping
+from collections.abc import Mapping
 import copy
 import datetime
 import json
+import urllib
 
 import cachetools
-import six
-from six.moves import urllib
 
 from google.auth import _helpers
 from google.auth import _service_account_info
@@ -123,7 +118,7 @@
         return json.loads(section_bytes.decode("utf-8"))
     except ValueError as caught_exc:
         new_exc = ValueError("Can't parse segment: {0}".format(section_bytes))
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
 
 def _unverified_decode(token):
@@ -241,19 +236,16 @@
 
     try:
         verifier_cls = _ALGORITHM_TO_VERIFIER_CLASS[key_alg]
-    except KeyError as exc:
+    except KeyError as caught_exc:
         if key_alg in _CRYPTOGRAPHY_BASED_ALGORITHMS:
-            six.raise_from(
-                ValueError(
-                    "The key algorithm {} requires the cryptography package "
-                    "to be installed.".format(key_alg)
-                ),
-                exc,
+            msg = (
+                "The key algorithm {} requires the cryptography package "
+                "to be installed."
             )
         else:
-            six.raise_from(
-                ValueError("Unsupported signature algorithm {}".format(key_alg)), exc
-            )
+            msg = "Unsupported signature algorithm {}"
+        new_exc = ValueError(msg.format(key_alg))
+        raise new_exc from caught_exc
 
     # If certs is specified as a dictionary of key IDs to certificates, then
     # use the certificate identified by the key ID in the token header.
diff --git a/google/auth/transport/__init__.py b/google/auth/transport/__init__.py
index 374e7b4..d1b035d 100644
--- a/google/auth/transport/__init__.py
+++ b/google/auth/transport/__init__.py
@@ -25,11 +25,9 @@
 """
 
 import abc
+import http.client
 
-import six
-from six.moves import http_client
-
-DEFAULT_REFRESH_STATUS_CODES = (http_client.UNAUTHORIZED,)
+DEFAULT_REFRESH_STATUS_CODES = (http.client.UNAUTHORIZED,)
 """Sequence[int]:  Which HTTP status code indicate that credentials should be
 refreshed and a request should be retried.
 """
@@ -38,8 +36,7 @@
 """int: How many times to refresh the credentials and retry a request."""
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Response(object):
+class Response(object, metaclass=abc.ABCMeta):
     """HTTP Response data."""
 
     @abc.abstractproperty
@@ -58,8 +55,7 @@
         raise NotImplementedError("data must be implemented.")
 
 
-@six.add_metaclass(abc.ABCMeta)
-class Request(object):
+class Request(object, metaclass=abc.ABCMeta):
     """Interface for a callable that makes HTTP requests.
 
     Specific transport implementations should provide an implementation of
diff --git a/google/auth/transport/_aiohttp_requests.py b/google/auth/transport/_aiohttp_requests.py
index ab7dfef..ee94043 100644
--- a/google/auth/transport/_aiohttp_requests.py
+++ b/google/auth/transport/_aiohttp_requests.py
@@ -24,7 +24,6 @@
 import functools
 
 import aiohttp
-import six
 import urllib3
 
 from google.auth import exceptions
@@ -191,11 +190,11 @@
 
         except aiohttp.ClientError as caught_exc:
             new_exc = exceptions.TransportError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         except asyncio.TimeoutError as caught_exc:
             new_exc = exceptions.TransportError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
 
 class AuthorizedSession(aiohttp.ClientSession):
diff --git a/google/auth/transport/_http_client.py b/google/auth/transport/_http_client.py
index c153763..679087f 100644
--- a/google/auth/transport/_http_client.py
+++ b/google/auth/transport/_http_client.py
@@ -14,12 +14,10 @@
 
 """Transport adapter for http.client, for internal use only."""
 
+import http.client
 import logging
 import socket
-
-import six
-from six.moves import http_client
-from six.moves import urllib
+import urllib
 
 from google.auth import exceptions
 from google.auth import transport
@@ -98,7 +96,7 @@
                 "was specified".format(parts.scheme)
             )
 
-        connection = http_client.HTTPConnection(parts.netloc, timeout=timeout)
+        connection = http.client.HTTPConnection(parts.netloc, timeout=timeout)
 
         try:
             _LOGGER.debug("Making request: %s %s", method, url)
@@ -107,9 +105,9 @@
             response = connection.getresponse()
             return Response(response)
 
-        except (http_client.HTTPException, socket.error) as caught_exc:
+        except (http.client.HTTPException, socket.error) as caught_exc:
             new_exc = exceptions.TransportError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         finally:
             connection.close()
diff --git a/google/auth/transport/_mtls_helper.py b/google/auth/transport/_mtls_helper.py
index 4dccb10..1b9b9c2 100644
--- a/google/auth/transport/_mtls_helper.py
+++ b/google/auth/transport/_mtls_helper.py
@@ -20,8 +20,6 @@
 import re
 import subprocess
 
-import six
-
 from google.auth import exceptions
 
 CONTEXT_AWARE_METADATA_PATH = "~/.secureConnect/context_aware_metadata.json"
@@ -82,7 +80,7 @@
             metadata = json.load(f)
     except ValueError as caught_exc:
         new_exc = exceptions.ClientCertError(caught_exc)
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
     return metadata
 
@@ -110,7 +108,7 @@
         stdout, stderr = process.communicate()
     except OSError as caught_exc:
         new_exc = exceptions.ClientCertError(caught_exc)
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
     # Check cert provider command execution error.
     if process.returncode != 0:
diff --git a/google/auth/transport/grpc.py b/google/auth/transport/grpc.py
index c47cb3d..160dc94 100644
--- a/google/auth/transport/grpc.py
+++ b/google/auth/transport/grpc.py
@@ -19,8 +19,6 @@
 import logging
 import os
 
-import six
-
 from google.auth import environment_vars
 from google.auth import exceptions
 from google.auth.transport import _mtls_helper
@@ -29,13 +27,11 @@
 try:
     import grpc
 except ImportError as caught_exc:  # pragma: NO COVER
-    six.raise_from(
-        ImportError(
-            "gRPC is not installed, please install the grpcio package "
-            "to use the gRPC transport."
-        ),
-        caught_exc,
+    new_exc = ImportError(
+        "gRPC is not installed, please install the grpcio package "
+        "to use the gRPC transport."
     )
+    raise new_exc from caught_exc
 
 _LOGGER = logging.getLogger(__name__)
 
@@ -88,7 +84,7 @@
             self._request, context.method_name, context.service_url, headers
         )
 
-        return list(six.iteritems(headers))
+        return list(headers.items())
 
     def __call__(self, context, callback):
         """Passes authorization metadata into the given callback.
@@ -337,7 +333,7 @@
                 )
             except exceptions.ClientCertError as caught_exc:
                 new_exc = exceptions.MutualTLSChannelError(caught_exc)
-                six.raise_from(new_exc, caught_exc)
+                raise new_exc from caught_exc
         else:
             self._ssl_credentials = grpc.ssl_channel_credentials()
 
diff --git a/google/auth/transport/mtls.py b/google/auth/transport/mtls.py
index b40bfbe..c570761 100644
--- a/google/auth/transport/mtls.py
+++ b/google/auth/transport/mtls.py
@@ -14,8 +14,6 @@
 
 """Utilites for mutual TLS."""
 
-import six
-
 from google.auth import exceptions
 from google.auth.transport import _mtls_helper
 
@@ -53,7 +51,7 @@
             _, cert_bytes, key_bytes = _mtls_helper.get_client_cert_and_key()
         except (OSError, RuntimeError, ValueError) as caught_exc:
             new_exc = exceptions.MutualTLSChannelError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         return cert_bytes, key_bytes
 
@@ -98,7 +96,7 @@
                 key_file.write(key_bytes)
         except (exceptions.ClientCertError, OSError) as caught_exc:
             new_exc = exceptions.MutualTLSChannelError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         return cert_path, key_path, passphrase_bytes
 
diff --git a/google/auth/transport/requests.py b/google/auth/transport/requests.py
index 817176b..2cb6942 100644
--- a/google/auth/transport/requests.py
+++ b/google/auth/transport/requests.py
@@ -25,21 +25,16 @@
 try:
     import requests
 except ImportError as caught_exc:  # pragma: NO COVER
-    import six
-
-    six.raise_from(
-        ImportError(
-            "The requests library is not installed, please install the "
-            "requests package to use the requests transport."
-        ),
-        caught_exc,
+    new_exc = ImportError(
+        "The requests library is not installed, please install the "
+        "requests package to use the requests transport."
     )
+    raise new_exc from caught_exc
 import requests.adapters  # pylint: disable=ungrouped-imports
 import requests.exceptions  # pylint: disable=ungrouped-imports
 from requests.packages.urllib3.util.ssl_ import (
     create_urllib3_context,
 )  # pylint: disable=ungrouped-imports
-import six  # pylint: disable=ungrouped-imports
 
 from google.auth import environment_vars
 from google.auth import exceptions
@@ -186,7 +181,7 @@
             return _Response(response)
         except requests.exceptions.RequestException as caught_exc:
             new_exc = exceptions.TransportError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
 
 class _MutualTlsAdapter(requests.adapters.HTTPAdapter):
@@ -396,7 +391,7 @@
             import OpenSSL
         except ImportError as caught_exc:
             new_exc = exceptions.MutualTLSChannelError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         try:
             (
@@ -416,7 +411,7 @@
             OpenSSL.crypto.Error,
         ) as caught_exc:
             new_exc = exceptions.MutualTLSChannelError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
     def request(
         self,
diff --git a/google/auth/transport/urllib3.py b/google/auth/transport/urllib3.py
index 6a2504d..aa7188c 100644
--- a/google/auth/transport/urllib3.py
+++ b/google/auth/transport/urllib3.py
@@ -34,16 +34,11 @@
 try:
     import urllib3
 except ImportError as caught_exc:  # pragma: NO COVER
-    import six
-
-    six.raise_from(
-        ImportError(
-            "The urllib3 library is not installed, please install the "
-            "urllib3 package to use the urllib3 transport."
-        ),
-        caught_exc,
+    new_exc = ImportError(
+        "The urllib3 library is not installed, please install the "
+        "urllib3 package to use the urllib3 transport."
     )
-import six
+    raise new_exc from caught_exc
 import urllib3.exceptions  # pylint: disable=ungrouped-imports
 
 from google.auth import environment_vars
@@ -142,7 +137,7 @@
             return _Response(response)
         except urllib3.exceptions.HTTPError as caught_exc:
             new_exc = exceptions.TransportError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
 
 def _make_default_http():
@@ -334,7 +329,7 @@
             import OpenSSL
         except ImportError as caught_exc:
             new_exc = exceptions.MutualTLSChannelError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         try:
             found_cert_key, cert, key = transport._mtls_helper.get_client_cert_and_key(
@@ -351,7 +346,7 @@
             OpenSSL.crypto.Error,
         ) as caught_exc:
             new_exc = exceptions.MutualTLSChannelError(caught_exc)
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
         if self._has_user_provided_http:
             self._has_user_provided_http = False
diff --git a/google/oauth2/_client.py b/google/oauth2/_client.py
index 2f4e847..f819371 100644
--- a/google/oauth2/_client.py
+++ b/google/oauth2/_client.py
@@ -24,11 +24,9 @@
 """
 
 import datetime
+import http.client
 import json
-
-import six
-from six.moves import http_client
-from six.moves import urllib
+import urllib
 
 from google.auth import _helpers
 from google.auth import exceptions
@@ -120,7 +118,7 @@
         )
         response_data = json.loads(response_body)
 
-        if response.status == http_client.OK:
+        if response.status == http.client.OK:
             break
         else:
             error_desc = response_data.get("error_description") or ""
@@ -131,9 +129,9 @@
             ):
                 retry += 1
                 continue
-            return response.status == http_client.OK, response_data
+            return response.status == http.client.OK, response_data
 
-    return response.status == http_client.OK, response_data
+    return response.status == http.client.OK, response_data
 
 
 def _token_endpoint_request(
@@ -196,7 +194,7 @@
         access_token = response_data["access_token"]
     except KeyError as caught_exc:
         new_exc = exceptions.RefreshError("No access token in response.", response_data)
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
     expiry = _parse_expiry(response_data)
 
@@ -236,7 +234,7 @@
         id_token = response_data["id_token"]
     except KeyError as caught_exc:
         new_exc = exceptions.RefreshError("No ID token in response.", response_data)
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
     payload = jwt.decode(id_token, verify=False)
     expiry = datetime.datetime.utcfromtimestamp(payload["exp"])
@@ -265,7 +263,7 @@
         access_token = response_data["access_token"]
     except KeyError as caught_exc:
         new_exc = exceptions.RefreshError("No access token in response.", response_data)
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
     refresh_token = response_data.get("refresh_token", refresh_token)
     expiry = _parse_expiry(response_data)
diff --git a/google/oauth2/_client_async.py b/google/oauth2/_client_async.py
index cf51211..8849023 100644
--- a/google/oauth2/_client_async.py
+++ b/google/oauth2/_client_async.py
@@ -24,11 +24,9 @@
 """
 
 import datetime
+import http.client
 import json
-
-import six
-from six.moves import http_client
-from six.moves import urllib
+import urllib
 
 from google.auth import exceptions
 from google.auth import jwt
@@ -85,7 +83,7 @@
 
         response_data = json.loads(response_body)
 
-        if response.status == http_client.OK:
+        if response.status == http.client.OK:
             break
         else:
             error_desc = response_data.get("error_description") or ""
@@ -96,9 +94,9 @@
             ):
                 retry += 1
                 continue
-            return response.status == http_client.OK, response_data
+            return response.status == http.client.OK, response_data
 
-    return response.status == http_client.OK, response_data
+    return response.status == http.client.OK, response_data
 
 
 async def _token_endpoint_request(
@@ -161,7 +159,7 @@
         access_token = response_data["access_token"]
     except KeyError as caught_exc:
         new_exc = exceptions.RefreshError("No access token in response.", response_data)
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
     expiry = client._parse_expiry(response_data)
 
@@ -201,7 +199,7 @@
         id_token = response_data["id_token"]
     except KeyError as caught_exc:
         new_exc = exceptions.RefreshError("No ID token in response.", response_data)
-        six.raise_from(new_exc, caught_exc)
+        raise new_exc from caught_exc
 
     payload = jwt.decode(id_token, verify=False)
     expiry = datetime.datetime.utcfromtimestamp(payload["exp"])
diff --git a/google/oauth2/_id_token_async.py b/google/oauth2/_id_token_async.py
index ab681a9..a4a526d 100644
--- a/google/oauth2/_id_token_async.py
+++ b/google/oauth2/_id_token_async.py
@@ -58,12 +58,10 @@
 .. _CacheControl: https://cachecontrol.readthedocs.io
 """
 
+import http.client
 import json
 import os
 
-import six
-from six.moves import http_client
-
 from google.auth import environment_vars
 from google.auth import exceptions
 from google.auth import jwt
@@ -88,7 +86,7 @@
     """
     response = await request(certs_url, method="GET")
 
-    if response.status != http_client.OK:
+    if response.status != http.client.OK:
         raise exceptions.TransportError(
             "Could not fetch certificates at {}".format(certs_url)
         )
@@ -243,10 +241,10 @@
                 "GOOGLE_APPLICATION_CREDENTIALS is not valid service account credentials.",
                 caught_exc,
             )
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
-    # 2. Try to fetch ID token from metada server if it exists. The code works for GAE and
-    # Cloud Run metadata server as well.
+    # 2. Try to fetch ID token from metada server if it exists. The code works
+    # for GAE and Cloud Run metadata server as well.
     try:
         from google.auth import compute_engine
         from google.auth.compute_engine import _metadata
diff --git a/google/oauth2/_reauth_async.py b/google/oauth2/_reauth_async.py
index 09e0760..510578b 100644
--- a/google/oauth2/_reauth_async.py
+++ b/google/oauth2/_reauth_async.py
@@ -34,8 +34,6 @@
 
 import sys
 
-from six.moves import range
-
 from google.auth import exceptions
 from google.oauth2 import _client
 from google.oauth2 import _client_async
diff --git a/google/oauth2/challenges.py b/google/oauth2/challenges.py
index d0b070e..7756a80 100644
--- a/google/oauth2/challenges.py
+++ b/google/oauth2/challenges.py
@@ -20,8 +20,6 @@
 import getpass
 import sys
 
-import six
-
 from google.auth import _helpers
 from google.auth import exceptions
 
@@ -44,8 +42,7 @@
     return getpass.getpass(text)
 
 
-@six.add_metaclass(abc.ABCMeta)
-class ReauthChallenge(object):
+class ReauthChallenge(object, metaclass=abc.ABCMeta):
     """Base class for reauth challenges."""
 
     @property
diff --git a/google/oauth2/credentials.py b/google/oauth2/credentials.py
index 158249e..98fd71b 100644
--- a/google/oauth2/credentials.py
+++ b/google/oauth2/credentials.py
@@ -35,8 +35,6 @@
 import io
 import json
 
-import six
-
 from google.auth import _cloud_sdk
 from google.auth import _helpers
 from google.auth import credentials
@@ -336,7 +334,7 @@
             ValueError: If the info is not in the expected format.
         """
         keys_needed = set(("refresh_token", "client_id", "client_secret"))
-        missing = keys_needed.difference(six.iterkeys(info))
+        missing = keys_needed.difference(info)
 
         if missing:
             raise ValueError(
diff --git a/google/oauth2/id_token.py b/google/oauth2/id_token.py
index 540ccd1..25492ca 100644
--- a/google/oauth2/id_token.py
+++ b/google/oauth2/id_token.py
@@ -55,12 +55,10 @@
 .. _CacheControl: https://cachecontrol.readthedocs.io
 """
 
+import http.client
 import json
 import os
 
-import six
-from six.moves import http_client
-
 from google.auth import environment_vars
 from google.auth import exceptions
 from google.auth import jwt
@@ -97,7 +95,7 @@
     """
     response = request(certs_url, method="GET")
 
-    if response.status != http_client.OK:
+    if response.status != http.client.OK:
         raise exceptions.TransportError(
             "Could not fetch certificates at {}".format(certs_url)
         )
@@ -242,10 +240,10 @@
                 "GOOGLE_APPLICATION_CREDENTIALS is not valid service account credentials.",
                 caught_exc,
             )
-            six.raise_from(new_exc, caught_exc)
+            raise new_exc from caught_exc
 
-    # 2. Try to fetch ID token from metada server if it exists. The code works for GAE and
-    # Cloud Run metadata server as well.
+    # 2. Try to fetch ID token from metada server if it exists. The code
+    # works for GAE and Cloud Run metadata server as well.
     try:
         from google.auth import compute_engine
         from google.auth.compute_engine import _metadata
diff --git a/google/oauth2/reauth.py b/google/oauth2/reauth.py
index d914fe9..fc2629e 100644
--- a/google/oauth2/reauth.py
+++ b/google/oauth2/reauth.py
@@ -34,8 +34,6 @@
 
 import sys
 
-from six.moves import range
-
 from google.auth import exceptions
 from google.oauth2 import _client
 from google.oauth2 import challenges
diff --git a/google/oauth2/sts.py b/google/oauth2/sts.py
index ae3c014..9f2d68a 100644
--- a/google/oauth2/sts.py
+++ b/google/oauth2/sts.py
@@ -31,10 +31,9 @@
 .. _rfc8693 section 2.2.1: https://tools.ietf.org/html/rfc8693#section-2.2.1
 """
 
+import http.client
 import json
-
-from six.moves import http_client
-from six.moves import urllib
+import urllib
 
 from google.oauth2 import utils
 
@@ -146,7 +145,7 @@
         )
 
         # If non-200 response received, translate to OAuthError exception.
-        if response.status != http_client.OK:
+        if response.status != http.client.OK:
             utils.handle_error_response(response_body)
 
         response_data = json.loads(response_body)
diff --git a/google/oauth2/utils.py b/google/oauth2/utils.py
index 593f032..c57833d 100644
--- a/google/oauth2/utils.py
+++ b/google/oauth2/utils.py
@@ -45,8 +45,6 @@
 import enum
 import json
 
-import six
-
 from google.auth import exceptions
 
 
@@ -77,8 +75,7 @@
         self.client_secret = client_secret
 
 
-@six.add_metaclass(abc.ABCMeta)
-class OAuthClientAuthHandler(object):
+class OAuthClientAuthHandler(object, metaclass=abc.ABCMeta):
     """Abstract class for handling client authentication in OAuth-based
     operations.
     """