-
Notifications
You must be signed in to change notification settings - Fork 3.2k
User authentication API for applications #10612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
6da3cc6
6ff4e3e
348cfd3
a9499da
55c639b
bbe033b
a2e467a
5ded022
f1b4270
8281b29
c1c0235
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # ------------------------------------ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| # ------------------------------------ | ||
| import json | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing import Any | ||
|
|
||
|
|
||
| class AuthenticationRecord(object): | ||
| """A record which can initialize :class:`DeviceCodeCredential` or :class:`InteractiveBrowserCredential`""" | ||
|
|
||
| def __init__(self, tenant_id, client_id, authority, home_account_id, username, **kwargs): | ||
| # type: (str, str, str, str, str, **Any) -> None | ||
| self._additional_data = kwargs | ||
| self._authority = authority | ||
| self._client_id = client_id | ||
| self._home_account_id = home_account_id | ||
| self._tenant_id = tenant_id | ||
| self._username = username | ||
|
|
||
| @property | ||
| def authority(self): | ||
| # type: () -> str | ||
| return self._authority | ||
|
|
||
| @property | ||
| def client_id(self): | ||
| # type: () -> str | ||
| return self._client_id | ||
|
|
||
| @property | ||
| def home_account_id(self): | ||
| # type: () -> str | ||
| return self._home_account_id | ||
|
|
||
| @property | ||
| def tenant_id(self): | ||
| # type: () -> str | ||
| return self._tenant_id | ||
|
|
||
| @property | ||
| def username(self): | ||
| # type: () -> str | ||
| """The authenticated user's username""" | ||
| return self._username | ||
|
|
||
| @property | ||
| def additional_data(self): | ||
| # type: () -> dict | ||
| """Keyword arguments serialized with the record""" | ||
|
|
||
| return dict(self._additional_data) | ||
chlowell marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def __getitem__(self, key): | ||
| return getattr(self, key, None) or self._additional_data[key] | ||
chlowell marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| @classmethod | ||
| def deserialize(cls, json_string): | ||
| # type: (str) -> AuthenticationRecord | ||
| """Deserialize a record from JSON""" | ||
|
|
||
| deserialized = json.loads(json_string) | ||
|
|
||
| return cls( | ||
| authority=deserialized.pop("authority"), | ||
| client_id=deserialized.pop("client_id"), | ||
| home_account_id=deserialized.pop("home_account_id"), | ||
| tenant_id=deserialized.pop("tenant_id"), | ||
| username=deserialized.pop("username"), | ||
| **deserialized | ||
| ) | ||
|
|
||
| def serialize(self, **kwargs): | ||
| # type: (**Any) -> str | ||
| """Serialize the record and any keyword arguments to JSON""" | ||
|
|
||
| record = dict( | ||
| { | ||
| "authority": self._authority, | ||
| "client_id": self._client_id, | ||
| "home_account_id": self._home_account_id, | ||
| "tenant_id": self._tenant_id, | ||
| "username": self._username, | ||
| }, | ||
| **kwargs | ||
| ) | ||
|
|
||
| return json.dumps(record) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,37 @@ | |
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| # ------------------------------------ | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| from azure.core.exceptions import ClientAuthenticationError | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing import Any, Optional, Sequence | ||
|
|
||
|
|
||
| class CredentialUnavailableError(ClientAuthenticationError): | ||
| """The credential did not attempt to authenticate because required data or state is unavailable.""" | ||
|
|
||
|
|
||
| class AuthenticationRequiredError(CredentialUnavailableError): | ||
|
||
| """Interactive authentication is required to acquire a token.""" | ||
|
|
||
| def __init__(self, scopes, message=None, error_details=None, **kwargs): | ||
| # type: (Sequence[str], Optional[str], Optional[str], **Any) -> None | ||
| self._scopes = scopes | ||
| self._error_details = error_details | ||
| if not message: | ||
| message = "Interactive authentication is required to get a token. Call 'authenticate' to begin." | ||
| super(AuthenticationRequiredError, self).__init__(message=message, **kwargs) | ||
|
|
||
| @property | ||
| def scopes(self): | ||
| # type: () -> Sequence[str] | ||
| """Scopes requested during the failed authentication""" | ||
| return self._scopes | ||
|
|
||
| @property | ||
| def error_details(self): | ||
| # type: () -> Optional[str] | ||
| """Additional authentication error details from Azure Active Directory""" | ||
| return self._error_details | ||
Uh oh!
There was an error while loading. Please reload this page.