diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9762d0c..70032ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,14 @@
 
 [1]: https://pypi.org/project/google-auth/#history
 
+### [1.10.1](https://www.github.com/googleapis/google-auth-library-python/compare/v1.10.0...v1.10.1) (2020-01-10)
+
+
+### Bug Fixes
+
+* **google.auth.compute_engine.metadata:** add retry to google.auth.compute_engine._metadata.get() ([#398](https://www.github.com/googleapis/google-auth-library-python/issues/398)) ([af29c1a](https://www.github.com/googleapis/google-auth-library-python/commit/af29c1a9fd9282b38867961e4053f74f018a3815)), closes [#211](https://www.github.com/googleapis/google-auth-library-python/issues/211) [#323](https://www.github.com/googleapis/google-auth-library-python/issues/323) [#323](https://www.github.com/googleapis/google-auth-library-python/issues/323) [#211](https://www.github.com/googleapis/google-auth-library-python/issues/211)
+* always pass body of type bytes to `google.auth.transport.Request` ([#421](https://www.github.com/googleapis/google-auth-library-python/issues/421)) ([a57a770](https://www.github.com/googleapis/google-auth-library-python/commit/a57a7708cfea635b5030f8c7ba10c967715f9a87)), closes [#318](https://www.github.com/googleapis/google-auth-library-python/issues/318)
+
 ## [1.10.0](https://www.github.com/googleapis/google-auth-library-python/compare/v1.9.0...v1.10.0) (2019-12-18)
 
 
diff --git a/google/auth/compute_engine/_metadata.py b/google/auth/compute_engine/_metadata.py
index f4fae72..30cd3d4 100644
--- a/google/auth/compute_engine/_metadata.py
+++ b/google/auth/compute_engine/_metadata.py
@@ -99,7 +99,7 @@ def ping(request, timeout=_METADATA_DEFAULT_TIMEOUT, retry_count=3):
     return False
 
 
-def get(request, path, root=_METADATA_ROOT, recursive=False):
+def get(request, path, root=_METADATA_ROOT, recursive=False, retry_count=5):
     """Fetch a resource from the metadata server.
 
     Args:
@@ -111,6 +111,8 @@ def get(request, path, root=_METADATA_ROOT, recursive=False):
         recursive (bool): Whether to do a recursive query of metadata. See
             https://cloud.google.com/compute/docs/metadata#aggcontents for more
             details.
+        retry_count (int): How many times to attempt connecting to metadata
+            server using above timeout.
 
     Returns:
         Union[Mapping, str]: If the metadata server returns JSON, a mapping of
@@ -129,7 +131,24 @@ def get(request, path, root=_METADATA_ROOT, recursive=False):
 
     url = _helpers.update_query(base_url, query_params)
 
-    response = request(url=url, method="GET", headers=_METADATA_HEADERS)
+    retries = 0
+    while retries < retry_count:
+        try:
+            response = request(url=url, method="GET", headers=_METADATA_HEADERS)
+            break
+
+        except exceptions.TransportError:
+            _LOGGER.info(
+                "Compute Engine Metadata server unavailable on" "attempt %s of %s",
+                retries + 1,
+                retry_count,
+            )
+            retries += 1
+    else:
+        raise exceptions.TransportError(
+            "Failed to retrieve {} from the Google Compute Engine"
+            "metadata service. Compute Engine Metadata server unavailable".format(url)
+        )
 
     if response.status == http_client.OK:
         content = _helpers.from_bytes(response.data)
diff --git a/google/auth/iam.py b/google/auth/iam.py
index a438726..0ab5b55 100644
--- a/google/auth/iam.py
+++ b/google/auth/iam.py
@@ -70,7 +70,9 @@ class Signer(crypt.Signer):
         method = "POST"
         url = _SIGN_BLOB_URI.format(self._service_account_email)
         headers = {}
-        body = json.dumps({"bytesToSign": base64.b64encode(message).decode("utf-8")})
+        body = json.dumps(
+            {"bytesToSign": base64.b64encode(message).decode("utf-8")}
+        ).encode("utf-8")
 
         self._credentials.before_request(self._request, method, url, headers)
         response = self._request(url=url, method=method, body=body, headers=headers)
diff --git a/google/auth/impersonated_credentials.py b/google/auth/impersonated_credentials.py
index 70fa5dc..bc7031e 100644
--- a/google/auth/impersonated_credentials.py
+++ b/google/auth/impersonated_credentials.py
@@ -84,7 +84,7 @@ def _make_iam_token_request(request, principal, headers, body):
     """
     iam_endpoint = _IAM_ENDPOINT.format(principal)
 
-    body = json.dumps(body)
+    body = json.dumps(body).encode("utf-8")
 
     response = request(url=iam_endpoint, method="POST", headers=headers, body=body)
 
diff --git a/google/auth/jwt.py b/google/auth/jwt.py
index a30c575..361c456 100644
--- a/google/auth/jwt.py
+++ b/google/auth/jwt.py
@@ -40,7 +40,10 @@ You can also skip verification::
 
 """
 
-import collections
+try:
+    from collections.abc import Mapping
+except ImportError: # Python 2.7 compatibility
+    from collections import Mapping
 import copy
 import datetime
 import json
@@ -215,7 +218,7 @@ def decode(token, certs=None, verify=True, audience=None):
 
     # 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.
-    if isinstance(certs, collections.Mapping):
+    if isinstance(certs, Mapping):
         key_id = header.get("kid")
         if key_id:
             if key_id not in certs:
diff --git a/google/oauth2/_client.py b/google/oauth2/_client.py
index 4cf7a7f..4ba31a8 100644
--- a/google/oauth2/_client.py
+++ b/google/oauth2/_client.py
@@ -95,7 +95,7 @@ def _token_endpoint_request(request, token_uri, body):
         google.auth.exceptions.RefreshError: If the token endpoint returned
             an error.
     """
-    body = urllib.parse.urlencode(body)
+    body = urllib.parse.urlencode(body).encode("utf-8")
     headers = {"content-type": _URLENCODED_CONTENT_TYPE}
 
     retry = 0
diff --git a/setup.py b/setup.py
index 954ce17..1b5eac4 100644
--- a/setup.py
+++ b/setup.py
@@ -30,7 +30,7 @@ DEPENDENCIES = (
 with io.open("README.rst", "r") as fh:
     long_description = fh.read()
 
-version = "1.10.0"
+version = "1.10.1"
 
 setup(
     name="google-auth",

Failure with Python 3.9 due to use of deprecated collections.Mapping
#### Environment details

  - OS: Linux
  - Python version: 3.9 alpha 2
  - pip version: 19.3.1
  - `google-auth` version: 1.10.0

#### Steps to reproduce

  1. Use Python 3.9
  2. Attempt to decode an ID Token:
    google.oauth2.id_token.verify_oauth2_token()...

Expected results:
decoded ID token

Actual results:
AttributeError: module 'collections' has no attribute 'Mapping'
see full crash at:
AttributeError: module 'collections' has no attribute 'Mapping'

Further details:
collections.Mapping was moved to collections.abc.Mapping in Python 3.3 but mapped back to collections up to Python 3.8. In Python 3.9 the legacy mapping is removed so we break. See:
https://docs.python.org/3/library/collections.html#

diff --git a/tests/compute_engine/test__metadata.py b/tests/compute_engine/test__metadata.py
index bd06b74..0898e1f 100644
--- a/tests/compute_engine/test__metadata.py
+++ b/tests/compute_engine/test__metadata.py
@@ -30,14 +30,17 @@ from google.auth.compute_engine import _metadata
 PATH = "instance/service-accounts/default"
 
 
-def make_request(data, status=http_client.OK, headers=None):
+def make_request(data, status=http_client.OK, headers=None, retry=False):
     response = mock.create_autospec(transport.Response, instance=True)
     response.status = status
     response.data = _helpers.to_bytes(data)
     response.headers = headers or {}
 
     request = mock.create_autospec(transport.Request)
-    request.return_value = response
+    if retry:
+        request.side_effect = [exceptions.TransportError(), response]
+    else:
+        request.return_value = response
 
     return request
 
@@ -55,6 +58,20 @@ def test_ping_success():
     )
 
 
+def test_ping_success_retry():
+    request = make_request("", headers=_metadata._METADATA_HEADERS, retry=True)
+
+    assert _metadata.ping(request)
+
+    request.assert_called_with(
+        method="GET",
+        url=_metadata._METADATA_IP_ROOT,
+        headers=_metadata._METADATA_HEADERS,
+        timeout=_metadata._METADATA_DEFAULT_TIMEOUT,
+    )
+    assert request.call_count == 2
+
+
 def test_ping_failure_bad_flavor():
     request = make_request("", headers={_metadata._METADATA_FLAVOR_HEADER: "meep"})
 
@@ -105,6 +122,25 @@ def test_get_success_json():
     assert result[key] == value
 
 
+def test_get_success_retry():
+    key, value = "foo", "bar"
+
+    data = json.dumps({key: value})
+    request = make_request(
+        data, headers={"content-type": "application/json"}, retry=True
+    )
+
+    result = _metadata.get(request, PATH)
+
+    request.assert_called_with(
+        method="GET",
+        url=_metadata._METADATA_ROOT + PATH,
+        headers=_metadata._METADATA_HEADERS,
+    )
+    assert request.call_count == 2
+    assert result[key] == value
+
+
 def test_get_success_text():
     data = "foobar"
     request = make_request(data, headers={"content-type": "text/plain"})
@@ -154,6 +190,23 @@ def test_get_failure():
     )
 
 
+def test_get_failure_connection_failed():
+    request = make_request("")
+    request.side_effect = exceptions.TransportError()
+
+    with pytest.raises(exceptions.TransportError) as excinfo:
+        _metadata.get(request, PATH)
+
+    assert excinfo.match(r"Compute Engine Metadata server unavailable")
+
+    request.assert_called_with(
+        method="GET",
+        url=_metadata._METADATA_ROOT + PATH,
+        headers=_metadata._METADATA_HEADERS,
+    )
+    assert request.call_count == 5
+
+
 def test_get_failure_bad_json():
     request = make_request("{", headers={"content-type": "application/json"})
 
diff --git a/tests/oauth2/test__client.py b/tests/oauth2/test__client.py
index 9cf59eb..052390a 100644
--- a/tests/oauth2/test__client.py
+++ b/tests/oauth2/test__client.py
@@ -96,7 +96,7 @@ def test__token_endpoint_request():
         method="POST",
         url="http://example.com",
         headers={"content-type": "application/x-www-form-urlencoded"},
-        body="test=params",
+        body="test=params".encode("utf-8"),
     )
 
     # Check result
@@ -131,7 +131,7 @@ def test__token_endpoint_request_internal_failure_error():
 
 
 def verify_request_params(request, params):
-    request_body = request.call_args[1]["body"]
+    request_body = request.call_args[1]["body"].decode("utf-8")
     request_params = urllib.parse.parse_qs(request_body)
 
     for key, value in six.iteritems(params):

pip install -e .[dev]
parse_log_pytest
requirements.txt
flask freezegun mock oauth2client pytest pytest-cov pytest-localserver requests urllib3 cryptography grpcio
apt-get update apt-get install -y gcc
3.9
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
blinker==1.9.0
cachetools==4.2.4
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
coverage==7.8.0
cryptography==44.0.2
exceptiongroup==1.2.2
Flask==3.1.0
freezegun==1.5.1
-e git+https://github.com/googleapis/google-auth-library-python.git@09001f95c3be2f0c495ce5324885f6ff9ddd855d#egg=google_auth
grpcio==1.71.0
httplib2==0.22.0
idna==3.10
importlib_metadata==8.6.1
iniconfig==2.1.0
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
mock==5.2.0
oauth2client==4.1.3
packaging==24.2
pluggy==1.5.0
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycparser==2.22
pyparsing==3.2.3
pytest==8.3.5
pytest-cov==6.0.0
pytest-localserver==0.9.0.post0
python-dateutil==2.9.0.post0
requests==2.32.3
rsa==4.0
six==1.17.0
tomli==2.2.1
urllib3==2.3.0
Werkzeug==3.1.3
zipp==3.21.0

name: google-auth-library-python
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - blinker==1.9.0
      - cachetools==4.2.4
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - coverage==7.8.0
      - cryptography==44.0.2
      - exceptiongroup==1.2.2
      - flask==3.1.0
      - freezegun==1.5.1
      - grpcio==1.71.0
      - httplib2==0.22.0
      - idna==3.10
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - itsdangerous==2.2.0
      - jinja2==3.1.6
      - markupsafe==3.0.2
      - mock==5.2.0
      - oauth2client==4.1.3
      - packaging==24.2
      - pluggy==1.5.0
      - pyasn1==0.6.1
      - pyasn1-modules==0.4.2
      - pycparser==2.22
      - pyparsing==3.2.3
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - pytest-localserver==0.9.0.post0
      - python-dateutil==2.9.0.post0
      - requests==2.32.3
      - rsa==4.0
      - six==1.17.0
      - tomli==2.2.1
      - urllib3==2.3.0
      - werkzeug==3.1.3
      - zipp==3.21.0
prefix: /opt/conda/envs/google-auth-library-python

tests/compute_engine/test__metadata.py::test_get_success_retry tests/compute_engine/test__metadata.py::test_get_failure_connection_failed tests/oauth2/test__client.py::test__token_endpoint_request tests/oauth2/test__client.py::test_jwt_grant tests/oauth2/test__client.py::test_id_token_jwt_grant tests/oauth2/test__client.py::test_refresh_grant tests/oauth2/test__client.py::test_refresh_grant_with_scopes
tests/compute_engine/test__metadata.py::test_ping_success tests/compute_engine/test__metadata.py::test_ping_success_retry tests/compute_engine/test__metadata.py::test_ping_failure_bad_flavor tests/compute_engine/test__metadata.py::test_ping_failure_connection_failed tests/compute_engine/test__metadata.py::test_ping_success_custom_root tests/compute_engine/test__metadata.py::test_get_success_json tests/compute_engine/test__metadata.py::test_get_success_text tests/compute_engine/test__metadata.py::test_get_success_custom_root tests/compute_engine/test__metadata.py::test_get_failure tests/compute_engine/test__metadata.py::test_get_failure_bad_json tests/compute_engine/test__metadata.py::test_get_project_id tests/compute_engine/test__metadata.py::test_get_service_account_token tests/compute_engine/test__metadata.py::test_get_service_account_info tests/oauth2/test__client.py::test__handle_error_response tests/oauth2/test__client.py::test__handle_error_response_non_json tests/oauth2/test__client.py::test__parse_expiry tests/oauth2/test__client.py::test__parse_expiry_none tests/oauth2/test__client.py::test__token_endpoint_request_error tests/oauth2/test__client.py::test__token_endpoint_request_internal_failure_error tests/oauth2/test__client.py::test_jwt_grant_no_access_token tests/oauth2/test__client.py::test_id_token_jwt_grant_no_access_token tests/oauth2/test__client.py::test_refresh_grant_no_access_token
google/oauth2/_client.py google/auth/impersonated_credentials.py setup.py CHANGELOG.md google/auth/jwt.py google/auth/compute_engine/_metadata.py google/auth/iam.py
google/oauth2/_client.py google/auth/impersonated_credentials.py setup.py CHANGELOG.md google/auth/jwt.py google/auth/compute_engine/_metadata.py google/auth/iam.py