feat: allow scopes for self signed jwt (#776)
* feat: allow scopes for self signed jwt
* Update service_account.py
* add http changes
* Update google/auth/jwt.py
diff --git a/tests/oauth2/test_service_account.py b/tests/oauth2/test_service_account.py
index 648541e..5852d37 100644
--- a/tests/oauth2/test_service_account.py
+++ b/tests/oauth2/test_service_account.py
@@ -155,6 +155,13 @@
new_credentials.apply(hdrs, token="tok")
assert "x-goog-user-project" in hdrs
+ def test__with_always_use_jwt_access(self):
+ credentials = self.make_credentials()
+ assert not credentials._always_use_jwt_access
+
+ new_credentials = credentials.with_always_use_jwt_access(True)
+ assert new_credentials._always_use_jwt_access
+
def test__make_authorization_grant_assertion(self):
credentials = self.make_credentials()
token = credentials._make_authorization_grant_assertion()
@@ -225,6 +232,65 @@
# JWT should not be created if there are user-defined scopes
jwt.from_signing_credentials.assert_not_called()
+ @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True)
+ def test__create_self_signed_jwt_always_use_jwt_access_with_audience(self, jwt):
+ credentials = service_account.Credentials(
+ SIGNER,
+ self.SERVICE_ACCOUNT_EMAIL,
+ self.TOKEN_URI,
+ default_scopes=["bar", "foo"],
+ always_use_jwt_access=True,
+ )
+
+ audience = "https://pubsub.googleapis.com"
+ credentials._create_self_signed_jwt(audience)
+ jwt.from_signing_credentials.assert_called_once_with(credentials, audience)
+
+ @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True)
+ def test__create_self_signed_jwt_always_use_jwt_access_with_scopes(self, jwt):
+ credentials = service_account.Credentials(
+ SIGNER,
+ self.SERVICE_ACCOUNT_EMAIL,
+ self.TOKEN_URI,
+ scopes=["bar", "foo"],
+ always_use_jwt_access=True,
+ )
+
+ audience = "https://pubsub.googleapis.com"
+ credentials._create_self_signed_jwt(audience)
+ jwt.from_signing_credentials.assert_called_once_with(
+ credentials, None, additional_claims={"scope": "bar foo"}
+ )
+
+ @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True)
+ def test__create_self_signed_jwt_always_use_jwt_access_with_default_scopes(
+ self, jwt
+ ):
+ credentials = service_account.Credentials(
+ SIGNER,
+ self.SERVICE_ACCOUNT_EMAIL,
+ self.TOKEN_URI,
+ default_scopes=["bar", "foo"],
+ always_use_jwt_access=True,
+ )
+
+ credentials._create_self_signed_jwt(None)
+ jwt.from_signing_credentials.assert_called_once_with(
+ credentials, None, additional_claims={"scope": "bar foo"}
+ )
+
+ @mock.patch("google.auth.jwt.Credentials", instance=True, autospec=True)
+ def test__create_self_signed_jwt_always_use_jwt_access(self, jwt):
+ credentials = service_account.Credentials(
+ SIGNER,
+ self.SERVICE_ACCOUNT_EMAIL,
+ self.TOKEN_URI,
+ always_use_jwt_access=True,
+ )
+
+ credentials._create_self_signed_jwt(None)
+ jwt.from_signing_credentials.assert_not_called()
+
@mock.patch("google.oauth2._client.jwt_grant", autospec=True)
def test_refresh_success(self, jwt_grant):
credentials = self.make_credentials()
diff --git a/tests/test_jwt.py b/tests/test_jwt.py
index c5290eb..39c45bd 100644
--- a/tests/test_jwt.py
+++ b/tests/test_jwt.py
@@ -390,6 +390,18 @@
assert new_credentials._additional_claims == self.credentials._additional_claims
assert new_credentials._quota_project_id == self.credentials._quota_project_id
+ def test__make_jwt_without_audience(self):
+ cred = jwt.Credentials.from_service_account_info(
+ SERVICE_ACCOUNT_INFO.copy(),
+ subject=self.SUBJECT,
+ audience=None,
+ additional_claims={"scope": "foo bar"},
+ )
+ token, _ = cred._make_jwt()
+ payload = jwt.decode(token, PUBLIC_CERT_BYTES)
+ assert payload["scope"] == "foo bar"
+ assert "aud" not in payload
+
def test_with_quota_project(self):
quota_project_id = "project-foo"
diff --git a/tests/transport/test_grpc.py b/tests/transport/test_grpc.py
index 1602f4c..926c1bc 100644
--- a/tests/transport/test_grpc.py
+++ b/tests/transport/test_grpc.py
@@ -111,8 +111,7 @@
plugin._get_authorization_headers(context)
- # self-signed JWT should not be created when default_host is not set
- credentials._create_self_signed_jwt.assert_not_called()
+ credentials._create_self_signed_jwt.assert_called_once_with(None)
def test__get_authorization_headers_with_service_account_and_default_host(self):
credentials = mock.create_autospec(service_account.Credentials)
diff --git a/tests/transport/test_requests.py b/tests/transport/test_requests.py
index 3fdd17c..f494c14 100644
--- a/tests/transport/test_requests.py
+++ b/tests/transport/test_requests.py
@@ -378,7 +378,7 @@
authed_session = google.auth.transport.requests.AuthorizedSession(credentials)
- authed_session.credentials._create_self_signed_jwt.assert_not_called()
+ authed_session.credentials._create_self_signed_jwt.assert_called_once_with(None)
def test_authorized_session_with_default_host(self):
default_host = "pubsub.googleapis.com"
diff --git a/tests/transport/test_urllib3.py b/tests/transport/test_urllib3.py
index 7c06934..e3848c1 100644
--- a/tests/transport/test_urllib3.py
+++ b/tests/transport/test_urllib3.py
@@ -164,7 +164,7 @@
authed_http = google.auth.transport.urllib3.AuthorizedHttp(credentials)
- authed_http.credentials._create_self_signed_jwt.assert_not_called()
+ authed_http.credentials._create_self_signed_jwt.assert_called_once_with(None)
def test_urlopen_with_default_host(self):
default_host = "pubsub.googleapis.com"