@@ -198,8 +198,9 @@ def __init__(
198198 authority or "https://login.microsoftonline.com/common/" ,
199199 self .http_client , validate_authority = validate_authority )
200200 # Here the self.authority is not the same type as authority in input
201+ self .client = None
201202 self .token_cache = token_cache or TokenCache ()
202- self .client = self . _build_client ( client_credential , self . authority )
203+ self ._client_credential = client_credential
203204 self .authority_groups = None
204205
205206 def _build_client (self , client_credential , authority ):
@@ -248,6 +249,12 @@ def _build_client(self, client_credential, authority):
248249 on_removing_rt = self .token_cache .remove_rt ,
249250 on_updating_rt = self .token_cache .update_rt )
250251
252+ def _get_client (self ):
253+ if not self .client :
254+ self .authority .initialize ()
255+ self .client = self ._build_client (self ._client_credential , self .authority )
256+ return self .client
257+
251258 def get_authorization_request_url (
252259 self ,
253260 scopes , # type: list[str]
@@ -307,6 +314,7 @@ def get_authorization_request_url(
307314 authority ,
308315 self .http_client
309316 ) if authority else self .authority
317+ the_authority .initialize ()
310318
311319 client = Client (
312320 {"authorization_endpoint" : the_authority .authorization_endpoint },
@@ -367,7 +375,7 @@ def acquire_token_by_authorization_code(
367375 # really empty.
368376 assert isinstance (scopes , list ), "Invalid parameter type"
369377 self ._validate_ssh_cert_input_data (kwargs .get ("data" , {}))
370- return self .client .obtain_token_by_authorization_code (
378+ return self ._get_client () .obtain_token_by_authorization_code (
371379 code , redirect_uri = redirect_uri ,
372380 scope = decorate_scope (scopes , self .client_id ),
373381 headers = {
@@ -391,6 +399,7 @@ def get_accounts(self, username=None):
391399 Your app can choose to display those information to end user,
392400 and allow user to choose one of his/her accounts to proceed.
393401 """
402+ self .authority .initialize ()
394403 accounts = self ._find_msal_accounts (environment = self .authority .instance )
395404 if not accounts : # Now try other aliases of this authority instance
396405 for alias in self ._get_authority_aliases (self .authority .instance ):
@@ -543,6 +552,7 @@ def acquire_token_silent_with_error(
543552 # authority,
544553 # self.http_client,
545554 # ) if authority else self.authority
555+ self .authority .initialize ()
546556 result = self ._acquire_token_silent_from_cache_and_possibly_refresh_it (
547557 scopes , account , self .authority , force_refresh = force_refresh ,
548558 correlation_id = correlation_id ,
@@ -555,6 +565,7 @@ def acquire_token_silent_with_error(
555565 "https://" + alias + "/" + self .authority .tenant ,
556566 self .http_client ,
557567 validate_authority = False )
568+ the_authority .initialize ()
558569 result = self ._acquire_token_silent_from_cache_and_possibly_refresh_it (
559570 scopes , account , the_authority , force_refresh = force_refresh ,
560571 correlation_id = correlation_id ,
@@ -724,7 +735,7 @@ def acquire_token_by_refresh_token(self, refresh_token, scopes):
724735 * A dict contains "error" and some other keys, when error happened.
725736 * A dict contains no "error" key means migration was successful.
726737 """
727- return self .client .obtain_token_by_refresh_token (
738+ return self ._get_client () .obtain_token_by_refresh_token (
728739 refresh_token ,
729740 decorate_scope (scopes , self .client_id ),
730741 rt_getter = lambda rt : rt ,
@@ -754,7 +765,7 @@ def initiate_device_flow(self, scopes=None, **kwargs):
754765 - an error response would contain some other readable key/value pairs.
755766 """
756767 correlation_id = _get_new_correlation_id ()
757- flow = self .client .initiate_device_flow (
768+ flow = self ._get_client () .initiate_device_flow (
758769 scope = decorate_scope (scopes or [], self .client_id ),
759770 headers = {
760771 CLIENT_REQUEST_ID : correlation_id ,
@@ -778,7 +789,7 @@ def acquire_token_by_device_flow(self, flow, **kwargs):
778789 - A successful response would contain "access_token" key,
779790 - an error response would contain "error" and usually "error_description".
780791 """
781- return self .client .obtain_token_by_device_flow (
792+ return self ._get_client () .obtain_token_by_device_flow (
782793 flow ,
783794 data = dict (kwargs .pop ("data" , {}), code = flow ["device_code" ]),
784795 # 2018-10-4 Hack:
@@ -815,14 +826,15 @@ def acquire_token_by_username_password(
815826 CLIENT_CURRENT_TELEMETRY : _build_current_telemetry_request_header (
816827 self .ACQUIRE_TOKEN_BY_USERNAME_PASSWORD_ID ),
817828 }
829+ self .authority .initialize ()
818830 if not self .authority .is_adfs :
819831 user_realm_result = self .authority .user_realm_discovery (
820832 username , correlation_id = headers [CLIENT_REQUEST_ID ])
821833 if user_realm_result .get ("account_type" ) == "Federated" :
822834 return self ._acquire_token_by_username_password_federated (
823835 user_realm_result , username , password , scopes = scopes ,
824836 headers = headers , ** kwargs )
825- return self .client .obtain_token_by_username_password (
837+ return self ._get_client () .obtain_token_by_username_password (
826838 username , password , scope = scopes ,
827839 headers = headers ,
828840 ** kwargs )
@@ -851,16 +863,16 @@ def _acquire_token_by_username_password_federated(
851863 GRANT_TYPE_SAML1_1 = 'urn:ietf:params:oauth:grant-type:saml1_1-bearer'
852864 grant_type = {
853865 SAML_TOKEN_TYPE_V1 : GRANT_TYPE_SAML1_1 ,
854- SAML_TOKEN_TYPE_V2 : self . client .GRANT_TYPE_SAML2 ,
866+ SAML_TOKEN_TYPE_V2 : Client .GRANT_TYPE_SAML2 ,
855867 WSS_SAML_TOKEN_PROFILE_V1_1 : GRANT_TYPE_SAML1_1 ,
856- WSS_SAML_TOKEN_PROFILE_V2 : self . client .GRANT_TYPE_SAML2
868+ WSS_SAML_TOKEN_PROFILE_V2 : Client .GRANT_TYPE_SAML2
857869 }.get (wstrust_result .get ("type" ))
858870 if not grant_type :
859871 raise RuntimeError (
860872 "RSTR returned unknown token type: %s" , wstrust_result .get ("type" ))
861- self . client .grant_assertion_encoders .setdefault ( # Register a non-standard type
862- grant_type , self . client .encode_saml_assertion )
863- return self .client .obtain_token_by_assertion (
873+ Client .grant_assertion_encoders .setdefault ( # Register a non-standard type
874+ grant_type , Client .encode_saml_assertion )
875+ return self ._get_client () .obtain_token_by_assertion (
864876 wstrust_result ["token" ], grant_type , scope = scopes , ** kwargs )
865877
866878
@@ -878,7 +890,7 @@ def acquire_token_for_client(self, scopes, **kwargs):
878890 - an error response would contain "error" and usually "error_description".
879891 """
880892 # TBD: force_refresh behavior
881- return self .client .obtain_token_for_client (
893+ return self ._get_client () .obtain_token_for_client (
882894 scope = scopes , # This grant flow requires no scope decoration
883895 headers = {
884896 CLIENT_REQUEST_ID : _get_new_correlation_id (),
@@ -910,9 +922,9 @@ def acquire_token_on_behalf_of(self, user_assertion, scopes, **kwargs):
910922 """
911923 # The implementation is NOT based on Token Exchange
912924 # https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16
913- return self .client .obtain_token_by_assertion ( # bases on assertion RFC 7521
925+ return self ._get_client () .obtain_token_by_assertion ( # bases on assertion RFC 7521
914926 user_assertion ,
915- self . client .GRANT_TYPE_JWT , # IDTs and AAD ATs are all JWTs
927+ Client .GRANT_TYPE_JWT , # IDTs and AAD ATs are all JWTs
916928 scope = decorate_scope (scopes , self .client_id ), # Decoration is used for:
917929 # 1. Explicitly requesting an RT, without relying on AAD default
918930 # behavior, even though it currently still issues an RT.
0 commit comments