Add `google.oauth2.service_account.IDTokenCredentials`. (#234)

diff --git a/google/oauth2/_client.py b/google/oauth2/_client.py
index 66251df..dc35be2 100644
--- a/google/oauth2/_client.py
+++ b/google/oauth2/_client.py
@@ -32,6 +32,7 @@
 
 from google.auth import _helpers
 from google.auth import exceptions
+from google.auth import jwt
 
 _URLENCODED_CONTENT_TYPE = 'application/x-www-form-urlencoded'
 _JWT_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
@@ -155,6 +156,51 @@
     return access_token, expiry, response_data
 
 
+def id_token_jwt_grant(request, token_uri, assertion):
+    """Implements the JWT Profile for OAuth 2.0 Authorization Grants, but
+    requests an OpenID Connect ID Token instead of an access token.
+
+    This is a variant on the standard JWT Profile that is currently unique
+    to Google. This was added for the benefit of authenticating to services
+    that require ID Tokens instead of access tokens or JWT bearer tokens.
+
+    Args:
+        request (google.auth.transport.Request): A callable used to make
+            HTTP requests.
+        token_uri (str): The OAuth 2.0 authorization server's token endpoint
+            URI.
+        assertion (str): JWT token signed by a service account. The token's
+            payload must include a ``target_audience`` claim.
+
+    Returns:
+        Tuple[str, Optional[datetime], Mapping[str, str]]:
+            The (encoded) Open ID Connect ID Token, expiration, and additional
+            data returned by the endpoint.
+
+    Raises:
+        google.auth.exceptions.RefreshError: If the token endpoint returned
+            an error.
+    """
+    body = {
+        'assertion': assertion,
+        'grant_type': _JWT_GRANT_TYPE,
+    }
+
+    response_data = _token_endpoint_request(request, token_uri, body)
+
+    try:
+        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)
+
+    payload = jwt.decode(id_token, verify=False)
+    expiry = datetime.datetime.utcfromtimestamp(payload['exp'])
+
+    return id_token, expiry, response_data
+
+
 def refresh_grant(request, token_uri, refresh_token, client_id, client_secret):
     """Implements the OAuth 2.0 refresh token grant.