У меня довольно простой проект ASP.NET, в котором установлена аутентификация Azure AD. Он использует CookieAuthentication по умолчанию и использует единый вход Azure AD для входа в систему.
Поэтому я не могу понять, что если я войду в систему и оставлю страницу открытой в течение 1 часа - это истечение срока действия маркера доступа Azure AD. время просто перестает работать.
Чтобы избежать этого, я пытался молча обновить токен доступа до истечения срока его действия, но не удалось. Даже не уверен, почему приложение перестает работать, так как оно использует Cookie для авторизации и использует регистрацию в Azure AD только для аутентификации.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = (context) =>
{
var threshold = DateTime.UtcNow.AddMinutes(55);
if (context.Properties.ExpiresUtc < threshold)
{
var authManager = context.OwinContext.Authentication;
string signedInUserID = context.Identity.FindFirst(System.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
if (authContext == null)
authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID));
ClientCredential credential = new ClientCredential(clientId, appKey);
try
{
var result = authContext.AcquireTokenSilentAsync(graphResourceId, clientId).Result;
}
catch (AggregateException ex)
{
if (ex.InnerException.GetType() == typeof(AdalSilentTokenAcquisitionException))
{
var result = authContext.AcquireTokenAsync(graphResourceId, credential).Result;
}
}
}
return Task.FromResult(0);
}
}
});
Это ADALTokenCache.
public class ADALTokenCache : TokenCache
{
private ApplicationDbContext db = new ApplicationDbContext();
private string userId;
private UserTokenCache Cache;
public ADALTokenCache(string signedInUserId)
{
// Associate the cache to the current user of the web app
userId = signedInUserId;
this.AfterAccess = AfterAccessNotification;
this.BeforeAccess = BeforeAccessNotification;
this.BeforeWrite = BeforeWriteNotification;
// Look up the entry in the database
Cache = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
// Place the entry in memory
this.Deserialize((Cache == null) ? null : MachineKey.Unprotect(Cache.cacheBits,"ADALCache"));
}
// Clean up the database
public override void Clear()
{
base.Clear();
var cacheEntry = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
db.UserTokenCacheList.Remove(cacheEntry);
db.SaveChanges();
}
// Notification raised before ADAL accesses the cache.
// This is your chance to update the in-memory copy from the DB, if the in-memory version is stale
void BeforeAccessNotification(TokenCacheNotificationArgs args)
{
if (Cache == null)
{
// First time access
Cache = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
}
else
{
// Retrieve last write from the DB
var status = from e in db.UserTokenCacheList
where (e.webUserUniqueId == userId)
select new
{
LastWrite = e.LastWrite
};
// If the in-memory copy is older than the persistent copy
if (status.First().LastWrite > Cache.LastWrite)
{
// Read from from storage, update in-memory copy
Cache = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
}
}
this.Deserialize((Cache == null) ? null : MachineKey.Unprotect(Cache.cacheBits, "ADALCache"));
}
// Notification raised after ADAL accessed the cache.
// If the HasStateChanged flag is set, ADAL changed the content of the cache
void AfterAccessNotification(TokenCacheNotificationArgs args)
{
// If state changed
if (this.HasStateChanged)
{
Cache = new UserTokenCache
{
webUserUniqueId = userId,
cacheBits = MachineKey.Protect(this.Serialize(), "ADALCache"),
LastWrite = DateTime.Now
};
// Update the DB and the lastwrite
db.Entry(Cache).State = Cache.UserTokenCacheId == 0 ? EntityState.Added : EntityState.Modified;
db.SaveChanges();
this.HasStateChanged = false;
}
}
void BeforeWriteNotification(TokenCacheNotificationArgs args)
{
// If you want to ensure that no concurrent write take place, use this notification to place a lock on the entry
var t = args;
}
public override void DeleteItem(TokenCacheItem item)
{
base.DeleteItem(item);
}
}
Эточто я пробовал, но не работает. Буду признателен за любую помощь. Заранее спасибо.