feat: add quota project to base credentials class (#546)

diff --git a/google/auth/credentials.py b/google/auth/credentials.py
index 3cc976b..3f389b1 100644
--- a/google/auth/credentials.py
+++ b/google/auth/credentials.py
@@ -49,6 +49,8 @@
         self.expiry = None
         """Optional[datetime]: When the token expires and is no longer valid.
         If this is None, the token is assumed to never expire."""
+        self._quota_project_id = None
+        """Optional[str]: Project to use for quota and billing purposes."""
 
     @property
     def expired(self):
@@ -75,6 +77,11 @@
         """
         return self.token is not None and not self.expired
 
+    @property
+    def quota_project_id(self):
+        """Project to use for quota and billing purposes."""
+        return self._quota_project_id
+
     @abc.abstractmethod
     def refresh(self, request):
         """Refreshes the access token.
@@ -102,6 +109,8 @@
         headers["authorization"] = "Bearer {}".format(
             _helpers.from_bytes(token or self.token)
         )
+        if self.quota_project_id:
+            headers["x-goog-user-project"] = self.quota_project_id
 
     def before_request(self, request, method, url, headers):
         """Performs credential-specific before request logic.
@@ -124,6 +133,18 @@
             self.refresh(request)
         self.apply(headers)
 
+    def with_quota_project(self, quota_project_id):
+        """Returns a copy of these credentials with a modified quota project
+
+        Args:
+            quota_project_id (str): The project to use for quota and
+                billing purposes
+
+        Returns:
+            google.oauth2.credentials.Credentials: A new credentials instance.
+        """
+        raise NotImplementedError("This class does not support quota project.")
+
 
 class AnonymousCredentials(Credentials):
     """Credentials that do not provide any authentication information.
@@ -161,6 +182,9 @@
     def before_request(self, request, method, url, headers):
         """Anonymous credentials do nothing to the request."""
 
+    def with_quota_project(self, quota_project_id):
+        raise ValueError("Anonymous credentials don't support quota project.")
+
 
 @six.add_metaclass(abc.ABCMeta)
 class ReadOnlyScoped(object):