Skip to content
This repository was archived by the owner on Mar 6, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions google/auth/app_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ def refresh(self, request):

self.token, self.expiry = token, expiry

@property
def service_account_email(self):
"""The service account email."""
if self._service_account_id is None:
self._service_account_id = app_identity.get_service_account_name()
return self._service_account_id

@property
def requires_scopes(self):
"""Checks if the credentials requires scopes.
Expand Down
9 changes: 9 additions & 0 deletions google/auth/compute_engine/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ def refresh(self, request):
except exceptions.TransportError as exc:
raise exceptions.RefreshError(exc)

@property
def service_account_email(self):
"""The service account email.

.. note: This is not guaranteed to be set until :meth`refresh` has been
called.
"""
return self._service_account_email

@property
def requires_scopes(self):
"""False: Compute Engine credentials can not be scoped."""
Expand Down
5 changes: 5 additions & 0 deletions google/oauth2/service_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ def to_jwt_credentials(self):
issuer=self._service_account_email,
subject=self._service_account_email)

@property
def service_account_email(self):
"""The service account email."""
return self._service_account_email

@property
def requires_scopes(self):
"""Checks if the credentials requires scopes.
Expand Down
2 changes: 1 addition & 1 deletion system_tests/test_compute_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_refresh(http_request, token_info):
credentials.refresh(http_request)

assert credentials.token is not None
assert credentials._service_account_email is not None
assert credentials.service_account_email is not None

info = token_info(credentials.token)
info_scopes = _helpers.string_to_scopes(info['scope'])
Expand Down
2 changes: 1 addition & 1 deletion system_tests/test_service_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_refresh_success(http_request, credentials, token_info):

info = token_info(credentials.token)

assert info['email'] == credentials._service_account_email
assert info['email'] == credentials.service_account_email
info_scopes = _helpers.string_to_scopes(info['scope'])
assert set(info_scopes) == set([
'https://www.googleapis.com/auth/userinfo.email',
Expand Down
4 changes: 3 additions & 1 deletion tests/compute_engine/test_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def test_default_state(self):
assert not self.credentials.expired
# Scopes aren't needed
assert not self.credentials.requires_scopes
# Service account email hasn't been populated
assert self.credentials.service_account_email == 'default'

@mock.patch(
'google.auth._helpers.utcnow', return_value=datetime.datetime.min)
Expand All @@ -58,7 +60,7 @@ def test_refresh_success(self, get_mock, now_mock):
datetime.datetime.min + datetime.timedelta(seconds=500))

# Check the credential info
assert (self.credentials._service_account_email ==
assert (self.credentials.service_account_email ==

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

'service-account@example.com')
assert self.credentials._scopes == ['one', 'two']

Expand Down
8 changes: 4 additions & 4 deletions tests/oauth2/test_service_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def test_from_service_account_info(self):

assert (credentials._signer.key_id ==
SERVICE_ACCOUNT_INFO['private_key_id'])
assert (credentials._service_account_email ==
assert (credentials.service_account_email ==
SERVICE_ACCOUNT_INFO['client_email'])
assert credentials._token_uri == SERVICE_ACCOUNT_INFO['token_uri']

Expand All @@ -77,8 +77,8 @@ def test_from_service_account_info_args(self):
info, scopes=scopes, subject=subject,
additional_claims=additional_claims)

assert credentials.service_account_email == info['client_email']
assert credentials._signer.key_id == info['private_key_id']
assert credentials._service_account_email == info['client_email']
assert credentials._token_uri == info['token_uri']
assert credentials._scopes == scopes
assert credentials._subject == subject
Expand All @@ -90,8 +90,8 @@ def test_from_service_account_file(self):
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_JSON_FILE)

assert credentials.service_account_email == info['client_email']
assert credentials._signer.key_id == info['private_key_id']
assert credentials._service_account_email == info['client_email']
assert credentials._token_uri == info['token_uri']

def test_from_service_account_file_args(self):
Expand All @@ -104,8 +104,8 @@ def test_from_service_account_file_args(self):
SERVICE_ACCOUNT_JSON_FILE, subject=subject,
scopes=scopes, additional_claims=additional_claims)

assert credentials.service_account_email == info['client_email']
assert credentials._signer.key_id == info['private_key_id']
assert credentials._service_account_email == info['client_email']
assert credentials._token_uri == info['token_uri']
assert credentials._scopes == scopes
assert credentials._subject == subject
Expand Down
6 changes: 3 additions & 3 deletions tests/test__oauth2client.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test__convert_service_account_credentials():
new_credentials = _oauth2client._convert_service_account_credentials(
old_credentials)

assert (new_credentials._service_account_email ==
assert (new_credentials.service_account_email ==
old_credentials.service_account_email)
assert new_credentials._signer.key_id == old_credentials._private_key_id
assert new_credentials._token_uri == old_credentials.token_uri
Expand All @@ -68,7 +68,7 @@ def test__convert_service_account_credentials_with_jwt():
new_credentials = _oauth2client._convert_service_account_credentials(
old_credentials)

assert (new_credentials._service_account_email ==
assert (new_credentials.service_account_email ==
old_credentials.service_account_email)
assert new_credentials._signer.key_id == old_credentials._private_key_id
assert new_credentials._token_uri == old_credentials.token_uri
Expand All @@ -81,7 +81,7 @@ def test__convert_gce_app_assertion_credentials():
new_credentials = _oauth2client._convert_gce_app_assertion_credentials(
old_credentials)

assert (new_credentials._service_account_email ==
assert (new_credentials.service_account_email ==
old_credentials.service_account_email)


Expand Down
17 changes: 17 additions & 0 deletions tests/test_app_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,23 @@ def test_with_scopes(self, app_identity_mock):
assert scoped_credentials.has_scopes(['email'])
assert not scoped_credentials.requires_scopes

def test_service_account_email_implicit(self, app_identity_mock):
app_identity_mock.get_service_account_name.return_value = (
mock.sentinel.service_account_email)
credentials = app_engine.Credentials()

assert (credentials.service_account_email ==
mock.sentinel.service_account_email)
assert app_identity_mock.get_service_account_name.called

def test_service_account_email_explicit(self, app_identity_mock):
credentials = app_engine.Credentials(
service_account_id=mock.sentinel.service_account_email)

assert (credentials.service_account_email ==
mock.sentinel.service_account_email)
assert not app_identity_mock.get_service_account_name.called

@mock.patch(
'google.auth._helpers.utcnow',
return_value=datetime.datetime.min)
Expand Down