@@ -198,8 +198,9 @@ def __init__(
198
198
authority or "https://login.microsoftonline.com/common/" ,
199
199
self .http_client , validate_authority = validate_authority )
200
200
# Here the self.authority is not the same type as authority in input
201
+ self .client = None
201
202
self .token_cache = token_cache or TokenCache ()
202
- self .client = self . _build_client ( client_credential , self . authority )
203
+ self ._client_credential = client_credential
203
204
self .authority_groups = None
204
205
205
206
def _build_client (self , client_credential , authority ):
@@ -248,6 +249,12 @@ def _build_client(self, client_credential, authority):
248
249
on_removing_rt = self .token_cache .remove_rt ,
249
250
on_updating_rt = self .token_cache .update_rt )
250
251
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
+
251
258
def get_authorization_request_url (
252
259
self ,
253
260
scopes , # type: list[str]
@@ -307,6 +314,7 @@ def get_authorization_request_url(
307
314
authority ,
308
315
self .http_client
309
316
) if authority else self .authority
317
+ the_authority .initialize ()
310
318
311
319
client = Client (
312
320
{"authorization_endpoint" : the_authority .authorization_endpoint },
@@ -367,7 +375,7 @@ def acquire_token_by_authorization_code(
367
375
# really empty.
368
376
assert isinstance (scopes , list ), "Invalid parameter type"
369
377
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 (
371
379
code , redirect_uri = redirect_uri ,
372
380
scope = decorate_scope (scopes , self .client_id ),
373
381
headers = {
@@ -391,6 +399,7 @@ def get_accounts(self, username=None):
391
399
Your app can choose to display those information to end user,
392
400
and allow user to choose one of his/her accounts to proceed.
393
401
"""
402
+ self .authority .initialize ()
394
403
accounts = self ._find_msal_accounts (environment = self .authority .instance )
395
404
if not accounts : # Now try other aliases of this authority instance
396
405
for alias in self ._get_authority_aliases (self .authority .instance ):
@@ -543,6 +552,7 @@ def acquire_token_silent_with_error(
543
552
# authority,
544
553
# self.http_client,
545
554
# ) if authority else self.authority
555
+ self .authority .initialize ()
546
556
result = self ._acquire_token_silent_from_cache_and_possibly_refresh_it (
547
557
scopes , account , self .authority , force_refresh = force_refresh ,
548
558
correlation_id = correlation_id ,
@@ -555,6 +565,7 @@ def acquire_token_silent_with_error(
555
565
"https://" + alias + "/" + self .authority .tenant ,
556
566
self .http_client ,
557
567
validate_authority = False )
568
+ the_authority .initialize ()
558
569
result = self ._acquire_token_silent_from_cache_and_possibly_refresh_it (
559
570
scopes , account , the_authority , force_refresh = force_refresh ,
560
571
correlation_id = correlation_id ,
@@ -724,7 +735,7 @@ def acquire_token_by_refresh_token(self, refresh_token, scopes):
724
735
* A dict contains "error" and some other keys, when error happened.
725
736
* A dict contains no "error" key means migration was successful.
726
737
"""
727
- return self .client .obtain_token_by_refresh_token (
738
+ return self ._get_client () .obtain_token_by_refresh_token (
728
739
refresh_token ,
729
740
decorate_scope (scopes , self .client_id ),
730
741
rt_getter = lambda rt : rt ,
@@ -754,7 +765,7 @@ def initiate_device_flow(self, scopes=None, **kwargs):
754
765
- an error response would contain some other readable key/value pairs.
755
766
"""
756
767
correlation_id = _get_new_correlation_id ()
757
- flow = self .client .initiate_device_flow (
768
+ flow = self ._get_client () .initiate_device_flow (
758
769
scope = decorate_scope (scopes or [], self .client_id ),
759
770
headers = {
760
771
CLIENT_REQUEST_ID : correlation_id ,
@@ -778,7 +789,7 @@ def acquire_token_by_device_flow(self, flow, **kwargs):
778
789
- A successful response would contain "access_token" key,
779
790
- an error response would contain "error" and usually "error_description".
780
791
"""
781
- return self .client .obtain_token_by_device_flow (
792
+ return self ._get_client () .obtain_token_by_device_flow (
782
793
flow ,
783
794
data = dict (kwargs .pop ("data" , {}), code = flow ["device_code" ]),
784
795
# 2018-10-4 Hack:
@@ -815,14 +826,15 @@ def acquire_token_by_username_password(
815
826
CLIENT_CURRENT_TELEMETRY : _build_current_telemetry_request_header (
816
827
self .ACQUIRE_TOKEN_BY_USERNAME_PASSWORD_ID ),
817
828
}
829
+ self .authority .initialize ()
818
830
if not self .authority .is_adfs :
819
831
user_realm_result = self .authority .user_realm_discovery (
820
832
username , correlation_id = headers [CLIENT_REQUEST_ID ])
821
833
if user_realm_result .get ("account_type" ) == "Federated" :
822
834
return self ._acquire_token_by_username_password_federated (
823
835
user_realm_result , username , password , scopes = scopes ,
824
836
headers = headers , ** kwargs )
825
- return self .client .obtain_token_by_username_password (
837
+ return self ._get_client () .obtain_token_by_username_password (
826
838
username , password , scope = scopes ,
827
839
headers = headers ,
828
840
** kwargs )
@@ -851,16 +863,16 @@ def _acquire_token_by_username_password_federated(
851
863
GRANT_TYPE_SAML1_1 = 'urn:ietf:params:oauth:grant-type:saml1_1-bearer'
852
864
grant_type = {
853
865
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 ,
855
867
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
857
869
}.get (wstrust_result .get ("type" ))
858
870
if not grant_type :
859
871
raise RuntimeError (
860
872
"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 (
864
876
wstrust_result ["token" ], grant_type , scope = scopes , ** kwargs )
865
877
866
878
@@ -878,7 +890,7 @@ def acquire_token_for_client(self, scopes, **kwargs):
878
890
- an error response would contain "error" and usually "error_description".
879
891
"""
880
892
# TBD: force_refresh behavior
881
- return self .client .obtain_token_for_client (
893
+ return self ._get_client () .obtain_token_for_client (
882
894
scope = scopes , # This grant flow requires no scope decoration
883
895
headers = {
884
896
CLIENT_REQUEST_ID : _get_new_correlation_id (),
@@ -910,9 +922,9 @@ def acquire_token_on_behalf_of(self, user_assertion, scopes, **kwargs):
910
922
"""
911
923
# The implementation is NOT based on Token Exchange
912
924
# 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
914
926
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
916
928
scope = decorate_scope (scopes , self .client_id ), # Decoration is used for:
917
929
# 1. Explicitly requesting an RT, without relying on AAD default
918
930
# behavior, even though it currently still issues an RT.
0 commit comments