Skip to content

Commit 74f4fd3

Browse files
authored
Separate modules for client credential types (#11496)
1 parent 146bc86 commit 74f4fd3

File tree

8 files changed

+123
-94
lines changed

8 files changed

+123
-94
lines changed

sdk/identity/azure-identity/azure/identity/_credentials/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
# ------------------------------------
55
from .authorization_code import AuthorizationCodeCredential
66
from .browser import InteractiveBrowserCredential
7+
from .certificate import CertificateCredential
78
from .chained import ChainedTokenCredential
8-
from .client_credential import CertificateCredential, ClientSecretCredential
9+
from .client_secret import ClientSecretCredential
910
from .default import DefaultAzureCredential
1011
from .environment import EnvironmentCredential
1112
from .managed_identity import ManagedIdentityCredential
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
from typing import TYPE_CHECKING
6+
7+
from .._authn_client import AuthnClient
8+
from .._base import CertificateCredentialBase
9+
10+
if TYPE_CHECKING:
11+
from azure.core.credentials import AccessToken
12+
from typing import Any
13+
14+
15+
class CertificateCredential(CertificateCredentialBase):
16+
"""Authenticates as a service principal using a certificate.
17+
18+
:param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID.
19+
:param str client_id: the service principal's client ID
20+
:param str certificate_path: path to a PEM-encoded certificate file including the private key.
21+
22+
:keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com',
23+
the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities`
24+
defines authorities for other clouds.
25+
:keyword password: The certificate's password. If a unicode string, it will be encoded as UTF-8. If the certificate
26+
requires a different encoding, pass appropriately encoded bytes instead.
27+
:paramtype password: str or bytes
28+
"""
29+
30+
def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument
31+
# type: (*str, **Any) -> AccessToken
32+
"""Request an access token for `scopes`.
33+
34+
.. note:: This method is called by Azure SDK clients. It isn't intended for use in application code.
35+
36+
:param str scopes: desired scopes for the access token. This method requires at least one scope.
37+
:rtype: :class:`azure.core.credentials.AccessToken`
38+
:raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message``
39+
attribute gives a reason. Any error response from Azure Active Directory is available as the error's
40+
``response`` attribute.
41+
"""
42+
if not scopes:
43+
raise ValueError("'get_token' requires at least one scope")
44+
45+
token = self._client.get_cached_token(scopes)
46+
if not token:
47+
data = self._get_request_data(*scopes)
48+
token = self._client.request_token(scopes, form_data=data)
49+
return token
50+
51+
def _get_auth_client(self, tenant_id, **kwargs):
52+
return AuthnClient(tenant=tenant_id, **kwargs)

sdk/identity/azure-identity/azure/identity/_credentials/client_credential.py renamed to sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Licensed under the MIT License.
44
# ------------------------------------
55
from .._authn_client import AuthnClient
6-
from .._base import ClientSecretCredentialBase, CertificateCredentialBase
6+
from .._base import ClientSecretCredentialBase
77

88
try:
99
from typing import TYPE_CHECKING
@@ -12,7 +12,7 @@
1212

1313
if TYPE_CHECKING:
1414
# pylint:disable=unused-import,ungrouped-imports
15-
from typing import Any, Mapping
15+
from typing import Any
1616
from azure.core.credentials import AccessToken
1717

1818

@@ -53,43 +53,3 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument
5353
data = dict(self._form_data, scope=" ".join(scopes))
5454
token = self._client.request_token(scopes, form_data=data)
5555
return token
56-
57-
58-
class CertificateCredential(CertificateCredentialBase):
59-
"""Authenticates as a service principal using a certificate.
60-
61-
:param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID.
62-
:param str client_id: the service principal's client ID
63-
:param str certificate_path: path to a PEM-encoded certificate file including the private key.
64-
65-
:keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com',
66-
the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities`
67-
defines authorities for other clouds.
68-
:keyword password: The certificate's password. If a unicode string, it will be encoded as UTF-8. If the certificate
69-
requires a different encoding, pass appropriately encoded bytes instead.
70-
:paramtype password: str or bytes
71-
"""
72-
73-
def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument
74-
# type: (*str, **Any) -> AccessToken
75-
"""Request an access token for `scopes`.
76-
77-
.. note:: This method is called by Azure SDK clients. It isn't intended for use in application code.
78-
79-
:param str scopes: desired scopes for the access token. This method requires at least one scope.
80-
:rtype: :class:`azure.core.credentials.AccessToken`
81-
:raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message``
82-
attribute gives a reason. Any error response from Azure Active Directory is available as the error's
83-
``response`` attribute.
84-
"""
85-
if not scopes:
86-
raise ValueError("'get_token' requires at least one scope")
87-
88-
token = self._client.get_cached_token(scopes)
89-
if not token:
90-
data = self._get_request_data(*scopes)
91-
token = self._client.request_token(scopes, form_data=data)
92-
return token
93-
94-
def _get_auth_client(self, tenant_id, **kwargs):
95-
return AuthnClient(tenant=tenant_id, **kwargs)

sdk/identity/azure-identity/azure/identity/_credentials/environment.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
from .. import CredentialUnavailableError
88
from .._constants import EnvironmentVariables
9-
from .client_credential import CertificateCredential, ClientSecretCredential
9+
from .certificate import CertificateCredential
10+
from .client_secret import ClientSecretCredential
1011
from .user_password import UsernamePasswordCredential
1112

1213

sdk/identity/azure-identity/azure/identity/aio/_credentials/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from .default import DefaultAzureCredential
88
from .environment import EnvironmentCredential
99
from .managed_identity import ManagedIdentityCredential
10-
from .client_credential import CertificateCredential, ClientSecretCredential
10+
from .certificate import CertificateCredential
11+
from .client_secret import ClientSecretCredential
1112
from .shared_cache import SharedTokenCacheCredential
1213
from .azure_cli import AzureCliCredential
1314

sdk/identity/azure-identity/azure/identity/aio/_credentials/client_credential.py renamed to sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,13 @@
66

77
from .base import AsyncCredentialBase
88
from .._authn_client import AsyncAuthnClient
9-
from ..._base import ClientSecretCredentialBase, CertificateCredentialBase
9+
from ..._base import CertificateCredentialBase
1010

1111
if TYPE_CHECKING:
12-
from typing import Any, Mapping
12+
from typing import Any
1313
from azure.core.credentials import AccessToken
1414

1515

16-
class ClientSecretCredential(ClientSecretCredentialBase, AsyncCredentialBase):
17-
"""Authenticates as a service principal using a client ID and client secret.
18-
19-
:param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID.
20-
:param str client_id: the service principal's client ID
21-
:param str client_secret: one of the service principal's client secrets
22-
23-
:keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com',
24-
the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities`
25-
defines authorities for other clouds.
26-
"""
27-
28-
def __init__(self, tenant_id: str, client_id: str, client_secret: str, **kwargs: "Any") -> None:
29-
super(ClientSecretCredential, self).__init__(tenant_id, client_id, client_secret, **kwargs)
30-
self._client = AsyncAuthnClient(tenant=tenant_id, **kwargs)
31-
32-
async def __aenter__(self):
33-
await self._client.__aenter__()
34-
return self
35-
36-
async def close(self):
37-
"""Close the credential's transport session."""
38-
39-
await self._client.__aexit__()
40-
41-
async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": # pylint:disable=unused-argument
42-
"""Asynchronously request an access token for `scopes`.
43-
44-
.. note:: This method is called by Azure SDK clients. It isn't intended for use in application code.
45-
46-
:param str scopes: desired scopes for the access token. This method requires at least one scope.
47-
:rtype: :class:`azure.core.credentials.AccessToken`
48-
:raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message``
49-
attribute gives a reason. Any error response from Azure Active Directory is available as the error's
50-
``response`` attribute.
51-
"""
52-
if not scopes:
53-
raise ValueError("'get_token' requires at least one scope")
54-
55-
token = self._client.get_cached_token(scopes)
56-
if not token:
57-
data = dict(self._form_data, scope=" ".join(scopes))
58-
token = await self._client.request_token(scopes, form_data=data)
59-
return token # type: ignore
60-
61-
6216
class CertificateCredential(CertificateCredentialBase, AsyncCredentialBase):
6317
"""Authenticates as a service principal using a certificate.
6418
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
from typing import TYPE_CHECKING
6+
7+
from .base import AsyncCredentialBase
8+
from .._authn_client import AsyncAuthnClient
9+
from ..._base import ClientSecretCredentialBase
10+
11+
if TYPE_CHECKING:
12+
from typing import Any
13+
from azure.core.credentials import AccessToken
14+
15+
16+
class ClientSecretCredential(ClientSecretCredentialBase, AsyncCredentialBase):
17+
"""Authenticates as a service principal using a client ID and client secret.
18+
19+
:param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID.
20+
:param str client_id: the service principal's client ID
21+
:param str client_secret: one of the service principal's client secrets
22+
23+
:keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com',
24+
the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities`
25+
defines authorities for other clouds.
26+
"""
27+
28+
def __init__(self, tenant_id: str, client_id: str, client_secret: str, **kwargs: "Any") -> None:
29+
super(ClientSecretCredential, self).__init__(tenant_id, client_id, client_secret, **kwargs)
30+
self._client = AsyncAuthnClient(tenant=tenant_id, **kwargs)
31+
32+
async def __aenter__(self):
33+
await self._client.__aenter__()
34+
return self
35+
36+
async def close(self):
37+
"""Close the credential's transport session."""
38+
39+
await self._client.__aexit__()
40+
41+
async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": # pylint:disable=unused-argument
42+
"""Asynchronously request an access token for `scopes`.
43+
44+
.. note:: This method is called by Azure SDK clients. It isn't intended for use in application code.
45+
46+
:param str scopes: desired scopes for the access token. This method requires at least one scope.
47+
:rtype: :class:`azure.core.credentials.AccessToken`
48+
:raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message``
49+
attribute gives a reason. Any error response from Azure Active Directory is available as the error's
50+
``response`` attribute.
51+
"""
52+
if not scopes:
53+
raise ValueError("'get_token' requires at least one scope")
54+
55+
token = self._client.get_cached_token(scopes)
56+
if not token:
57+
data = dict(self._form_data, scope=" ".join(scopes))
58+
token = await self._client.request_token(scopes, form_data=data)
59+
return token # type: ignore

sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
from ... import CredentialUnavailableError
99
from ..._constants import EnvironmentVariables
10-
from .client_credential import CertificateCredential, ClientSecretCredential
10+
from .certificate import CertificateCredential
11+
from .client_secret import ClientSecretCredential
1112
from .base import AsyncCredentialBase
1213

1314
if TYPE_CHECKING:

0 commit comments

Comments
 (0)