@@ -122,6 +122,19 @@ def wipe(dictionary, sensitive_fields): # Masks sensitive info
122122 default = str , # A workaround when assertion is in bytes in Python 3
123123 ))
124124
125+ def __parse_account (self , response , id_token_claims ):
126+ """Return client_info and home_account_id"""
127+ if "client_info" in response : # It happens when client_info and profile are in request
128+ client_info = json .loads (decode_part (response ["client_info" ]))
129+ if "uid" in client_info and "utid" in client_info :
130+ return client_info , "{uid}.{utid}" .format (** client_info )
131+ # https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/387
132+ if id_token_claims : # This would be an end user on ADFS-direct scenario
133+ sub = id_token_claims ["sub" ] # "sub" always exists, per OIDC specs
134+ return {"uid" : sub }, sub
135+ # client_credentials flow will reach this code path
136+ return {}, None
137+
125138 def __add (self , event , now = None ):
126139 # event typically contains: client_id, scope, token_endpoint,
127140 # response, params, data, grant_type
@@ -138,14 +151,7 @@ def __add(self, event, now=None):
138151 id_token_claims = (
139152 decode_id_token (id_token , client_id = event ["client_id" ])
140153 if id_token else {})
141- client_info = {}
142- home_account_id = None # It would remain None in client_credentials flow
143- if "client_info" in response : # We asked for it, and AAD will provide it
144- client_info = json .loads (decode_part (response ["client_info" ]))
145- home_account_id = "{uid}.{utid}" .format (** client_info )
146- elif id_token_claims : # This would be an end user on ADFS-direct scenario
147- client_info ["uid" ] = id_token_claims .get ("sub" )
148- home_account_id = id_token_claims .get ("sub" )
154+ client_info , home_account_id = self .__parse_account (response , id_token_claims )
149155
150156 target = ' ' .join (event .get ("scope" ) or []) # Per schema, we don't sort it
151157
0 commit comments