Skip to content

Commit 26f0689

Browse files
committed
Keep unfit RTs b/c they might be useful for others
Mark last_modification_time for RT
1 parent 78e9ccf commit 26f0689

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

msal/application.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,11 +918,20 @@ def _acquire_token_silent_by_finding_specific_refresh_token(
918918
client = self._build_client(self.client_credential, authority)
919919

920920
response = None # A distinguishable value to mean cache is empty
921-
for entry in matches:
921+
for entry in sorted( # Since unfit RTs would not be aggressively removed,
922+
# we start from newer RTs which are more likely fit.
923+
matches,
924+
key=lambda e: int(e.get("last_modification_time", "0")),
925+
reverse=True):
922926
logger.debug("Cache attempts an RT")
923927
response = client.obtain_token_by_refresh_token(
924928
entry, rt_getter=lambda token_item: token_item["secret"],
925-
on_removing_rt=rt_remover or self.token_cache.remove_rt,
929+
on_removing_rt=(rt_remover or self.token_cache.remove_rt)
930+
if # we can remove a RT when a single scope is an exact match
931+
len(scopes) == 1
932+
and set(entry.get("target", "").split()) <= set(scopes)
933+
else # otherwise keep the RT as it might work for a subset of scopes
934+
lambda rt_item: None, # No OP
926935
on_obtaining_tokens=lambda event: self.token_cache.add(dict(
927936
event,
928937
environment=authority.instance,

msal/token_cache.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ def __add(self, event, now=None):
148148
target = ' '.join(event.get("scope", [])) # Per schema, we don't sort it
149149

150150
with self._lock:
151+
now = int(time.time() if now is None else now)
151152

152153
if access_token:
153-
now = int(time.time() if now is None else now)
154154
expires_in = int( # AADv1-like endpoint returns a string
155155
response.get("expires_in", 3599))
156156
ext_expires_in = int( # AADv1-like endpoint returns a string
@@ -212,6 +212,7 @@ def __add(self, event, now=None):
212212
"environment": environment,
213213
"client_id": event.get("client_id"),
214214
"target": target, # Optional per schema though
215+
"last_modification_time": str(now), # Optional. Schema defines it as a string.
215216
}
216217
if "foci" in response:
217218
rt["family_id"] = response["foci"]
@@ -249,8 +250,10 @@ def remove_rt(self, rt_item):
249250

250251
def update_rt(self, rt_item, new_rt):
251252
assert rt_item.get("credential_type") == self.CredentialType.REFRESH_TOKEN
252-
return self.modify(
253-
self.CredentialType.REFRESH_TOKEN, rt_item, {"secret": new_rt})
253+
return self.modify(self.CredentialType.REFRESH_TOKEN, rt_item, {
254+
"secret": new_rt,
255+
"last_modification_time": str(int(time.time())), # Optional. Schema defines it as a string.
256+
})
254257

255258
def remove_at(self, at_item):
256259
assert at_item.get("credential_type") == self.CredentialType.ACCESS_TOKEN

tests/test_application.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ def setUp(self):
7373
self.client_id, authority=self.authority_url, token_cache=self.cache)
7474

7575
def test_cache_empty_will_be_returned_as_None(self):
76-
self.assertEqual(
77-
None, self.app.acquire_token_silent(['cache_miss'], self.account))
76+
self.app.token_cache = msal.SerializableTokenCache() # Reset it to empty
7877
self.assertEqual(
7978
None, self.app.acquire_token_silent_with_error(['cache_miss'], self.account))
8079

tests/test_token_cache.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def testAddByAad(self):
8484
'credential_type': 'RefreshToken',
8585
'environment': 'login.example.com',
8686
'home_account_id': "uid.utid",
87+
'last_modification_time': '1000',
8788
'secret': 'a refresh token',
8889
'target': 's2 s1 s3',
8990
},
@@ -157,6 +158,7 @@ def testAddByAdfs(self):
157158
'credential_type': 'RefreshToken',
158159
'environment': 'fs.msidlab8.com',
159160
'home_account_id': "subject",
161+
'last_modification_time': "1000",
160162
'secret': 'a refresh token',
161163
'target': 's2 s1 s3',
162164
},

0 commit comments

Comments
 (0)