-
Notifications
You must be signed in to change notification settings - Fork 6
/
DistributedTokenCache.cs
86 lines (81 loc) · 3.16 KB
/
DistributedTokenCache.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using ApiOnBehalfSample.Extensions;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Security.Claims;
namespace ApiOnBehalfSample.Services
{
public class DistributedTokenCache : TokenCache
{
private ClaimsPrincipal _claimsPrincipal;
private ILogger _logger;
private IDistributedCache _distributedCache;
private IDataProtector _protector;
private string _cacheKey;
public DistributedTokenCache(
ClaimsPrincipal claimsPrincipal,
IDistributedCache distributedCache,
ILoggerFactory loggerFactory,
IDataProtectionProvider dataProtectionProvider)
: base()
{
_claimsPrincipal = claimsPrincipal;
_cacheKey = BuildCacheKey(_claimsPrincipal);
_distributedCache = distributedCache;
_logger = loggerFactory.CreateLogger<DistributedTokenCache>();
_protector = dataProtectionProvider.CreateProtector(typeof(DistributedTokenCache).FullName);
AfterAccess = AfterAccessNotification;
LoadFromCache();
}
private static string BuildCacheKey(ClaimsPrincipal claimsPrincipal)
{
string clientId = claimsPrincipal.FindFirstValue("aud", true);
return string.Format(
"UserId:{0}::ClientId:{1}",
claimsPrincipal.GetObjectIdentifierValue(),
clientId);
}
/// <summary>
/// Attempts to load tokens from distributed cache.
/// </summary>
private void LoadFromCache()
{
byte[] cacheData = _distributedCache.Get(_cacheKey);
if (cacheData != null)
{
Deserialize(_protector.Unprotect(cacheData));
_logger.TokensRetrievedFromStore(_cacheKey);
}
}
public void AfterAccessNotification(TokenCacheNotificationArgs args)
{
if (HasStateChanged)
{
try
{
if (Count > 0)
{
_distributedCache.Set(_cacheKey, _protector.Protect(Serialize()));
_logger.TokensWrittenToStore(args.ClientId, args.UniqueId, args.Resource);
}
else
{
// There are no tokens for this user/client, so remove them from the cache.
// This was previously handled in an overridden Clear() method, but the built-in Clear() calls this
// after the dictionary is cleared.
_distributedCache.Remove(_cacheKey);
_logger.TokenCacheCleared(_claimsPrincipal.GetObjectIdentifierValue(false) ?? "<none>");
}
HasStateChanged = false;
}
catch (Exception exp)
{
_logger.WriteToCacheFailed(exp);
throw;
}
}
}
}
}