Closed
Description
PersistedTokenCache.deserialize
replaces an instance's in-memory data entirely but the new data isn't persisted until modify
is called. This introduces a couple opportunities for data loss:
- if
modify
is never called, the data is never persisted - if
find
is called immediately afterdeserialize
,PersistedTokenCache
will overwrite its deserialized data when the persistence class returns a modified time later than the last sync, or any time at all if the last sync time is still 0
For example:
from msal import SerializableTokenCache
from msal_extensions import FilePersistence, PersistedTokenCache
PATH = "file_persistence"
with open(PATH, "w"):
pass
cache_a = SerializableTokenCache()
cache_a.add({"scope": ["scope"], "response": {"access_token": "...", "client_id": "..."}})
cache_b = PersistedTokenCache(persistence=FilePersistence(PATH))
cache_b.deserialize(cache_a.serialize()) # cache_b has new data in memory but doesn't persist it
print("after deserialize: {}".format(cache_b._cache))
# cache_b.find deserializes the empty cache file, replacing data deserialized from cache_a
cache_b.find("AccessToken")
print("after find: {}".format(cache_b._cache)) # cache_b is now empty