Proactively refresh credentials when applying and treat a missing acces_token as invalid. (#469)
Closes #350, Supersedes #434
Note: This change reveals surprising behavior between default credentials and batches. If you allow `googleapiclient.discovery.build` to use default credentials *and* specify different credentials by providing `batch.execut()` with an explicit `http` argument, your individual requests will use the default credentials and *not* the credentials specified to the bathc http. To avoid this, tell `build` explicitly not to use default credentials by specifying `build(..., http=httplib2.Http()`.
For context, see:
https://github.com/google/google-api-python-client/pull/434#issuecomment-358439456
diff --git a/googleapiclient/_auth.py b/googleapiclient/_auth.py
index ada4ffb..9d6d363 100644
--- a/googleapiclient/_auth.py
+++ b/googleapiclient/_auth.py
@@ -120,6 +120,8 @@
def apply_credentials(credentials, headers):
# oauth2client and google-auth have the same interface for this.
+ if not is_valid(credentials):
+ refresh_credentials(credentials)
return credentials.apply(headers)
@@ -128,7 +130,9 @@
credentials, google.auth.credentials.Credentials):
return credentials.valid
else:
- return not credentials.access_token_expired
+ return (
+ credentials.access_token is not None and
+ not credentials.access_token_expired)
def get_credentials_from_http(http):
diff --git a/tests/test_http.py b/tests/test_http.py
index 9d48266..2109af7 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -71,6 +71,10 @@
self._access_token_expired = expired
@property
+ def access_token(self):
+ return self._bearer_token
+
+ @property
def access_token_expired(self):
return self._access_token_expired