@@ -124,6 +124,21 @@ def _get(self, credential_type, key, default=None): # O(1)
124124 with self ._lock :
125125 return self ._cache .get (credential_type , {}).get (key , default )
126126
127+ def _get_username_by_home_account_id (self , home_account_id , environment ):
128+ """Look up existing accounts with the same home_account_id to inherit username.
129+
130+ When broker returns a token without id_token (e.g. CachedRefreshToken path),
131+ the username would be empty. This method finds a previously cached account
132+ with the same home_account_id that has a non-empty username.
133+ """
134+ if not home_account_id :
135+ return None
136+ for entry in self ._cache .get (self .CredentialType .ACCOUNT , {}).values ():
137+ if (entry .get ("home_account_id" ) == home_account_id
138+ and entry .get ("username" )):
139+ return entry ["username" ]
140+ return None
141+
127142 @staticmethod
128143 def _is_matching (entry : dict , query : dict , target_set : set = None ) -> bool :
129144 query_with_lowercase_environment = {
@@ -295,6 +310,8 @@ def __add(self, event, now=None):
295310 "username" : _get_username (id_token_claims )
296311 or data .get ("username" ) # Falls back to ROPC username
297312 or event .get ("username" ) # Falls back to Federated ROPC username
313+ or self ._get_username_by_home_account_id (
314+ home_account_id , environment )
298315 or "" , # The schema does not like null
299316 "authority_type" : event .get (
300317 "authority_type" , # Honor caller's choice of authority_type
0 commit comments