/// <summary> /// Raised AFTER MSAL added the new token in its in-memory copy of the cache. /// This notification is called every time MSAL accessed the cache, not just when a write took place: /// If MSAL's current operation resulted in a cache change, the property TokenCacheNotificationArgs.HasStateChanged will be set to true. /// If that is the case, we call the TokenCache.Serialize() to get a binary blob representing the latest cache content – and persist it. /// </summary> /// <param name="args">Contains parameters used by the MSAL call accessing the cache.</param> private void UserTokenCacheAfterAccessNotification(TokenCacheNotificationArgs args) { SetSignedInUserFromNotificationArgs(args); // if state changed, i.e. new token obtained if (args.HasStateChanged && !string.IsNullOrWhiteSpace(GetSignedInUsersUniqueId())) { if (_inMemoryCache == null) { _inMemoryCache = new UserTokenCache { WebUserUniqueId = GetSignedInUsersUniqueId() }; } _inMemoryCache.CacheBits = _dataProtector.Protect(_userTokenCache.SerializeMsalV3()); _inMemoryCache.LastWrite = DateTime.Now; try { // Update the DB and the lastwrite _tokenCacheDb.Entry(_inMemoryCache).State = _inMemoryCache.UserTokenCacheId == 0 ? EntityState.Added : EntityState.Modified; _tokenCacheDb.SaveChanges(); } catch (DbUpdateConcurrencyException) { // Record already updated on a different thread, so just read the updated record ReadCacheForSignedInUser(); } } }