@@ -280,22 +280,47 @@ def _get_authority_aliases(self, instance):
280280 return [alias for alias in group if alias != instance ]
281281 return []
282282
283- def remove_account (self , home_account ):
284- """Remove all relevant RTs and ATs from token cache"""
285- owned_by_account = {
283+ def remove_account (self , account ):
284+ """Sign me out and forget me from token cache"""
285+ self ._forget_me (account )
286+
287+ def _sign_out (self , home_account ):
288+ # Remove all relevant RTs and ATs from token cache
289+ owned_by_home_account = {
286290 "environment" : home_account ["environment" ],
287291 "home_account_id" : home_account ["home_account_id" ],} # realm-independent
288- for rt in self .token_cache .find ( # Remove RTs, and RTs are realm-independent
289- TokenCache .CredentialType .REFRESH_TOKEN , query = owned_by_account ):
292+ app_metadata = self ._get_app_metadata (home_account ["environment" ])
293+ # Remove RTs/FRTs, and they are realm-independent
294+ for rt in [rt for rt in self .token_cache .find (
295+ TokenCache .CredentialType .REFRESH_TOKEN , query = owned_by_home_account )
296+ # Do RT's app ownership check as a precaution, in case family apps
297+ # and 3rd-party apps share same token cache, although they should not.
298+ if rt ["client_id" ] == self .client_id or (
299+ app_metadata .get ("family_id" ) # Now let's settle family business
300+ and rt .get ("family_id" ) == app_metadata ["family_id" ])
301+ ]:
290302 self .token_cache .remove_rt (rt )
291- for at in self .token_cache .find ( # Remove ATs, regardless of realm
292- TokenCache .CredentialType .ACCESS_TOKEN , query = owned_by_account ):
303+ for at in self .token_cache .find ( # Remove ATs
304+ # Regardless of realm, b/c we've removed realm-independent RTs anyway
305+ TokenCache .CredentialType .ACCESS_TOKEN , query = owned_by_home_account ):
306+ # To avoid the complexity of locating sibling family app's AT,
307+ # we skip AT's app ownership check.
308+ # It means ATs for other apps will also be removed, it is OK because:
309+ # * non-family apps are not supposed to share token cache to begin with;
310+ # * Even if it happens, we keep other app's RT already, so SSO still works
293311 self .token_cache .remove_at (at )
312+
313+ def _forget_me (self , home_account ):
314+ # It implies signout, and then also remove all relevant accounts and IDTs
315+ self ._sign_out (home_account )
316+ owned_by_home_account = {
317+ "environment" : home_account ["environment" ],
318+ "home_account_id" : home_account ["home_account_id" ],} # realm-independent
294319 for idt in self .token_cache .find ( # Remove IDTs, regardless of realm
295- TokenCache .CredentialType .ID_TOKEN , query = owned_by_account ):
320+ TokenCache .CredentialType .ID_TOKEN , query = owned_by_home_account ):
296321 self .token_cache .remove_idt (idt )
297322 for a in self .token_cache .find ( # Remove Accounts, regardless of realm
298- TokenCache .CredentialType .ACCOUNT , query = owned_by_account ):
323+ TokenCache .CredentialType .ACCOUNT , query = owned_by_home_account ):
299324 self .token_cache .remove_account (a )
300325
301326 def acquire_token_silent (
0 commit comments