11from dataclasses import dataclass , field
22from enum import Enum
3- from typing import Optional , Union , Callable , Any , List
3+ from typing import Optional , Any , List , Tuple , Iterable
44
55import requests
6+ from azure .identity import DefaultAzureCredential
67from msal import (
78 ConfidentialClientApplication ,
89 ManagedIdentityClient ,
@@ -41,69 +42,120 @@ class ServicePrincipalIdentityProviderConfig:
4142 scopes : Optional [List [str ]] = None
4243 timeout : Optional [float ] = None
4344 tenant_id : Optional [str ] = None
44- token_kwargs : Optional [dict ] = None
45+ token_kwargs : Optional [dict ] = field ( default_factory = dict )
4546 app_kwargs : Optional [dict ] = field (default_factory = dict )
4647
4748
48- class EntraIDIdentityProvider (IdentityProviderInterface ):
49- """
50- EntraID Identity Provider implementation.
51- It's recommended to use an additional factory methods to simplify object instantiation.
49+ @dataclass
50+ class DefaultAzureCredentialIdentityProviderConfig :
51+ scopes : Iterable [str ]
52+ additional_tenant_id : Optional [str ] = None
53+ authority : Optional [str ] = None
54+ token_kwargs : Optional [dict ] = field (default_factory = dict )
55+ app_kwargs : Optional [dict ] = field (default_factory = dict )
56+
5257
53- Methods: create_provider_from_managed_identity, create_provider_from_service_principal.
58+ class ManagedIdentityProvider (IdentityProviderInterface ):
59+ """
60+ Identity Provider implementation for Azure Managed Identity auth type.
5461 """
5562 def __init__ (
5663 self ,
57- app : Union [ManagedIdentityClient , ConfidentialClientApplication ],
58- scopes : List = [],
59- resource : str = '' ,
64+ app : ManagedIdentityClient ,
65+ resource : str ,
6066 ** kwargs
6167 ):
68+ """
69+ :param kwargs: See: :class:`ManagedIdentityClient` for additional configuration.
70+ """
6271 self ._app = app
63- self ._scopes = scopes
6472 self ._resource = resource
6573 self ._kwargs = kwargs
6674
6775 def request_token (self , force_refresh = False ) -> TokenInterface :
6876 """
69- Request token from identity provider.
70- Force refresh argument is optional and works only with Service Principal auth method.
77+ Request token from identity provider. Force refresh isn't supported for this provider type.
78+ """
79+ try :
80+ response = self ._app .acquire_token_for_client (resource = self ._resource , ** self ._kwargs )
81+
82+ if "error" in response :
83+ raise RequestTokenErr (response ["error_description" ])
84+ except Exception as e :
85+ raise RequestTokenErr (e )
86+
87+ return JWToken (response ["access_token" ])
7188
72- :param force_refresh:
73- :return: TokenInterface
89+
90+ class ServicePrincipalProvider (IdentityProviderInterface ):
91+ """
92+ Identity Provider implementation for Azure Service Principal auth type.
93+ """
94+ def __init__ (
95+ self ,
96+ app : ConfidentialClientApplication ,
97+ scopes : Optional [List [str ]] = None ,
98+ ** kwargs
99+ ):
100+ """
101+ :param kwargs: See: :class:`ConfidentialClientApplication` for additional configuration.
74102 """
75- if isinstance (self ._app , ManagedIdentityClient ):
76- return self ._get_token (self ._app .acquire_token_for_client , resource = self ._resource )
103+ self ._app = app
104+ self ._scopes = scopes
105+ self ._kwargs = kwargs
77106
107+ def request_token (self , force_refresh = False ) -> TokenInterface :
108+ """
109+ Request token from identity provider.
110+ """
78111 if force_refresh :
79112 self ._app .remove_tokens_for_client ()
80113
81- return self ._get_token (
82- self ._app .acquire_token_for_client ,
83- scopes = self ._scopes ,
84- ** self ._kwargs
85- )
86-
87- def _get_token (self , callback : Callable , ** kwargs ) -> JWToken :
88114 try :
89- response = callback ( ** kwargs )
115+ response = self . _app . acquire_token_for_client ( scopes = self . _scopes , ** self . _kwargs )
90116
91117 if "error" in response :
92118 raise RequestTokenErr (response ["error_description" ])
119+ except Exception as e :
120+ raise RequestTokenErr (e )
121+
122+ return JWToken (response ["access_token" ])
123+
124+
125+ class DefaultAzureCredentialProvider (IdentityProviderInterface ):
126+ """
127+ Identity Provider implementation for Default Azure Credential flow.
128+ """
129+
130+ def __init__ (
131+ self ,
132+ app : DefaultAzureCredential ,
133+ scopes : Tuple [str ],
134+ additional_tenant_id : Optional [str ] = None ,
135+ ** kwargs
136+ ):
137+ self ._app = app
138+ self ._scopes = scopes
139+ self ._additional_tenant_id = additional_tenant_id
140+ self ._kwargs = kwargs
93141
94- return JWToken (callback (** kwargs )["access_token" ])
142+ def request_token (self , force_refresh = False ) -> TokenInterface :
143+ try :
144+ response = self ._app .get_token (* self ._scopes , tenant_id = self ._additional_tenant_id , ** self ._kwargs )
95145 except Exception as e :
96146 raise RequestTokenErr (e )
97147
148+ return JWToken (response .token )
149+
98150
99- def _create_provider_from_managed_identity (config : ManagedIdentityProviderConfig ) -> EntraIDIdentityProvider :
151+ def _create_provider_from_managed_identity (config : ManagedIdentityProviderConfig ) -> ManagedIdentityProvider :
100152 """
101- Create an EntraID identity provider following Managed Identity auth flow.
153+ Create a Managed identity provider following Managed Identity auth flow.
102154
103155 :param config: Config for managed assigned identity provider
104156 See: :class:`ManagedIdentityClient` acquire_token_for_client method.
105157
106- :return: :class:`EntraIDIdentityProvider `
158+ :return: :class:`ManagedIdentityProvider `
107159 """
108160 if config .identity_type == ManagedIdentityType .USER_ASSIGNED :
109161 if config .id_type is None or config .id_value == '' :
@@ -118,16 +170,16 @@ def _create_provider_from_managed_identity(config: ManagedIdentityProviderConfig
118170 managed_identity = config .identity_type .value ()
119171
120172 app = ManagedIdentityClient (managed_identity , http_client = requests .Session ())
121- return EntraIDIdentityProvider (app , [] , config .resource , ** config .kwargs )
173+ return ManagedIdentityProvider (app , config .resource , ** config .kwargs )
122174
123175
124- def _create_provider_from_service_principal (config : ServicePrincipalIdentityProviderConfig ) -> EntraIDIdentityProvider :
176+ def _create_provider_from_service_principal (config : ServicePrincipalIdentityProviderConfig ) -> ServicePrincipalProvider :
125177 """
126- Create an EntraID identity provider following Service Principal auth flow.
178+ Create a Service Principal identity provider following Service Principal auth flow.
127179
128180 :param config: Config for service principal identity provider
129181
130- :return: :class:`EntraIDIdentityProvider `
182+ :return: :class:`ServicePrincipalProvider `
131183 See: :class:`ConfidentialClientApplication`.
132184 """
133185
@@ -146,4 +198,23 @@ def _create_provider_from_service_principal(config: ServicePrincipalIdentityProv
146198 authority = authority ,
147199 ** config .app_kwargs
148200 )
149- return EntraIDIdentityProvider (app , scopes , ** config .token_kwargs )
201+ return ServicePrincipalProvider (app , scopes , ** config .token_kwargs )
202+
203+
204+ def _create_provider_from_default_azure_credential (
205+ config : DefaultAzureCredentialIdentityProviderConfig
206+ ) -> DefaultAzureCredentialProvider :
207+ """
208+ Create a Default Azure Credential identity provider following Default Azure Credential flow.
209+
210+ :param config: Config for default Azure Credential identity provider
211+ :return: :class:`DefaultAzureCredentialProvider`
212+ See: :class:`DefaultAzureCredential`.
213+ """
214+
215+ app = DefaultAzureCredential (
216+ authority = config .authority ,
217+ ** config .app_kwargs
218+ )
219+
220+ return DefaultAzureCredentialProvider (app , config .scopes , config .additional_tenant_id , ** config .token_kwargs )
0 commit comments