Skip to content

Commit 2d7878a

Browse files
authored
feat: Add public API load_credentials_from_dict (#1326)
feat: Add public API load_credentials_from_dict to allow creating a default credential object from a dictionary. This resolves googleapis/google-auth-library-python#1313.
1 parent e768c70 commit 2d7878a

4 files changed

Lines changed: 72 additions & 2 deletions

File tree

packages/google-auth/google/auth/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@
1717
import logging
1818

1919
from google.auth import version as google_auth_version
20-
from google.auth._default import default, load_credentials_from_file
20+
from google.auth._default import (
21+
default,
22+
load_credentials_from_dict,
23+
load_credentials_from_file,
24+
)
2125

2226

2327
__version__ = google_auth_version.__version__
2428

2529

26-
__all__ = ["default", "load_credentials_from_file"]
30+
__all__ = ["default", "load_credentials_from_file", "load_credentials_from_dict"]
2731

2832
# Set default logging handler to avoid "No handler found" warnings.
2933
logging.getLogger(__name__).addHandler(logging.NullHandler())

packages/google-auth/google/auth/_default.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,50 @@ def load_credentials_from_file(
130130
)
131131

132132

133+
def load_credentials_from_dict(
134+
info, scopes=None, default_scopes=None, quota_project_id=None, request=None
135+
):
136+
"""Loads Google credentials from a dict.
137+
138+
The credentials file must be a service account key, stored authorized
139+
user credentials, external account credentials, or impersonated service
140+
account credentials.
141+
142+
Args:
143+
info (Dict[str, Any]): A dict object containing the credentials
144+
scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If
145+
specified, the credentials will automatically be scoped if
146+
necessary
147+
default_scopes (Optional[Sequence[str]]): Default scopes passed by a
148+
Google client library. Use 'scopes' for user-defined scopes.
149+
quota_project_id (Optional[str]): The project ID used for
150+
quota and billing.
151+
request (Optional[google.auth.transport.Request]): An object used to make
152+
HTTP requests. This is used to determine the associated project ID
153+
for a workload identity pool resource (external account credentials).
154+
If not specified, then it will use a
155+
google.auth.transport.requests.Request client to make requests.
156+
157+
Returns:
158+
Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded
159+
credentials and the project ID. Authorized user credentials do not
160+
have the project ID information. External account credentials project
161+
IDs may not always be determined.
162+
163+
Raises:
164+
google.auth.exceptions.DefaultCredentialsError: if the file is in the
165+
wrong format or is missing.
166+
"""
167+
if not isinstance(info, dict):
168+
raise exceptions.DefaultCredentialsError(
169+
"info object was of type {} but dict type was expected.".format(type(info))
170+
)
171+
172+
return _load_credentials_from_info(
173+
"dict object", info, scopes, default_scopes, quota_project_id, request
174+
)
175+
176+
133177
def _load_credentials_from_info(
134178
filename, info, scopes, default_scopes, quota_project_id, request
135179
):
0 Bytes
Binary file not shown.

packages/google-auth/tests/test__default.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,28 @@ def test_load_credentials_from_missing_file():
188188
assert excinfo.match(r"not found")
189189

190190

191+
def test_load_credentials_from_dict_non_dict_object():
192+
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
193+
_default.load_credentials_from_dict("")
194+
assert excinfo.match(r"dict type was expected")
195+
196+
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
197+
_default.load_credentials_from_dict(None)
198+
assert excinfo.match(r"dict type was expected")
199+
200+
with pytest.raises(exceptions.DefaultCredentialsError) as excinfo:
201+
_default.load_credentials_from_dict(1)
202+
assert excinfo.match(r"dict type was expected")
203+
204+
205+
def test_load_credentials_from_dict_authorized_user():
206+
credentials, project_id = _default.load_credentials_from_dict(
207+
AUTHORIZED_USER_FILE_DATA
208+
)
209+
assert isinstance(credentials, google.oauth2.credentials.Credentials)
210+
assert project_id is None
211+
212+
191213
def test_load_credentials_from_file_invalid_json(tmpdir):
192214
jsonfile = tmpdir.join("invalid.json")
193215
jsonfile.write("{")

0 commit comments

Comments
 (0)