@@ -16,44 +16,49 @@ public class PersistentTokenCache : TokenCache
1616 {
1717 // we are creating the MsalCacheHelper with a random guid based clientId to work around issue https://github.com/AzureAD/microsoft-authentication-extensions-for-dotnet/issues/98
1818 // This does not impact the functionality of the cacheHelper as the ClientId is only used to iterate accounts in the cache not for authentication purposes.
19- private static readonly string s_msalCacheClientId = Guid . NewGuid ( ) . ToString ( ) ;
20-
21- private static AsyncLockWithValue < MsalCacheHelper > cacheHelperLock = new AsyncLockWithValue < MsalCacheHelper > ( ) ;
22- private static AsyncLockWithValue < MsalCacheHelper > s_ProtectedCacheHelperLock = new AsyncLockWithValue < MsalCacheHelper > ( ) ;
23- private static AsyncLockWithValue < MsalCacheHelper > s_FallbackCacheHelperLock = new AsyncLockWithValue < MsalCacheHelper > ( ) ;
19+ internal static readonly string s_msalCacheClientId = Guid . NewGuid ( ) . ToString ( ) ;
2420 private readonly bool _allowUnencryptedStorage ;
2521 private readonly string _name ;
26-
27- /// <summary>
28- /// Creates a new instance of <see cref="PersistentTokenCache"/>.
29- /// </summary>
30- /// <param name="allowUnencryptedStorage"></param>
31- public PersistentTokenCache ( bool allowUnencryptedStorage = true )
32- {
33- _allowUnencryptedStorage = allowUnencryptedStorage ;
34- }
22+ private static AsyncLockWithValue < MsalCacheHelperWrapper > cacheHelperLock = new AsyncLockWithValue < MsalCacheHelperWrapper > ( ) ;
23+ private readonly MsalCacheHelperWrapper _cacheHelperWrapper ;
3524
3625 /// <summary>
3726 /// Creates a new instance of <see cref="PersistentTokenCache"/> with the specified options.
3827 /// </summary>
3928 /// <param name="options">Options controlling the storage of the <see cref="PersistentTokenCache"/>.</param>
40- public PersistentTokenCache ( PersistentTokenCacheOptions options )
29+ public PersistentTokenCache ( PersistentTokenCacheOptions options = null )
4130 {
4231 _allowUnencryptedStorage = options ? . AllowUnencryptedStorage ?? false ;
32+ _name = options ? . Name ?? Constants . DefaultMsalTokenCacheName ;
33+ _cacheHelperWrapper = new MsalCacheHelperWrapper ( ) ;
34+ }
4335
44- _name = options ? . Name ;
36+ internal PersistentTokenCache ( PersistentTokenCacheOptions options , MsalCacheHelperWrapper cacheHelperWrapper )
37+ {
38+ _allowUnencryptedStorage = options ? . AllowUnencryptedStorage ?? false ;
39+ _name = options ? . Name ?? Constants . DefaultMsalTokenCacheName ;
40+ _cacheHelperWrapper = cacheHelperWrapper ;
4541 }
4642
4743 internal override async Task RegisterCache ( bool async , ITokenCache tokenCache , CancellationToken cancellationToken )
4844 {
49- MsalCacheHelper cacheHelper = await GetCacheHelperAsync ( async , cancellationToken ) . ConfigureAwait( false) ;
45+ MsalCacheHelperWrapper cacheHelper = await GetCacheHelperAsync ( async , cancellationToken ) . ConfigureAwait( false) ;
5046
5147 cacheHelper. RegisterCache( tokenCache) ;
5248
5349 await base . RegisterCache ( async, tokenCache , cancellationToken ) . ConfigureAwait( false ) ;
5450 }
5551
56- private async Task < MsalCacheHelper > GetCacheHelperAsync ( bool async , CancellationToken cancellationToken )
52+ /// <summary>
53+ /// Resets the <see cref="cacheHelperLock"/> so that tests can validate multiple calls to <see cref="RegisterCache"/>
54+ /// This should only be used for testing.
55+ /// </summary>
56+ internal static void ResetWrapperCache ( )
57+ {
58+ cacheHelperLock = new AsyncLockWithValue < MsalCacheHelperWrapper > ( ) ;
59+ }
60+
61+ private async Task < MsalCacheHelperWrapper > GetCacheHelperAsync ( bool async , CancellationToken cancellationToken )
5762 {
5863 using var asyncLock = await cacheHelperLock . GetLockOrValueAsync ( async , cancellationToken ) . ConfigureAwait( false) ;
5964
@@ -62,19 +67,19 @@ private async Task<MsalCacheHelper> GetCacheHelperAsync(bool async, Cancellation
6267 return asyncLock. Value;
6368 }
6469
65- MsalCacheHelper cacheHelper;
70+ MsalCacheHelperWrapper cacheHelper;
6671
6772 try
6873 {
69- cacheHelper = string . IsNullOrEmpty ( _name ) ? await GetProtectedCacheHelperAsync ( async , cancellationToken ) . ConfigureAwait ( false ) : await GetProtectedCacheHelperAsync ( async , _name ) . ConfigureAwait ( false ) ;
74+ cacheHelper = await GetProtectedCacheHelperAsync ( async , _name ) . ConfigureAwait ( false ) ;
7075
7176 cacheHelper . VerifyPersistence ( ) ;
7277 }
7378 catch ( MsalCachePersistenceException )
7479 {
7580 if ( _allowUnencryptedStorage )
7681 {
77- cacheHelper = string . IsNullOrEmpty ( _name ) ? await GetFallbackCacheHelperAsync ( async , cancellationToken ) . ConfigureAwait ( false ) : await GetFallbackCacheHelperAsync ( async , _name ) . ConfigureAwait ( false ) ;
82+ cacheHelper = await GetFallbackCacheHelperAsync ( async , _name ) . ConfigureAwait ( false ) ;
7883
7984 cacheHelper . VerifyPersistence ( ) ;
8085 }
@@ -89,69 +94,43 @@ private async Task<MsalCacheHelper> GetCacheHelperAsync(bool async, Cancellation
8994 return cacheHelper ;
9095 }
9196
92- private static async Task < MsalCacheHelper > GetProtectedCacheHelperAsync ( bool async , CancellationToken cancellationToken )
93- {
94- using var asyncLock = await s_ProtectedCacheHelperLock . GetLockOrValueAsync ( async , cancellationToken ) . ConfigureAwait( false) ;
95-
96- if ( asyncLock. HasValue)
97- {
98- return asyncLock. Value;
99- }
100-
101- MsalCacheHelper cacheHelper = await GetProtectedCacheHelperAsync ( async , Constants . DefaultMsalTokenCacheName ) . ConfigureAwait ( false ) ;
102-
103- asyncLock . SetValue ( cacheHelper ) ;
104-
105- return cacheHelper ;
106- }
107-
108- private static async Task < MsalCacheHelper > GetProtectedCacheHelperAsync ( bool async , string name )
97+ private async Task < MsalCacheHelperWrapper > GetProtectedCacheHelperAsync ( bool async , string name )
10998 {
11099 StorageCreationProperties storageProperties = new StorageCreationPropertiesBuilder ( name , Constants . DefaultMsalTokenCacheDirectory , s_msalCacheClientId )
111100 . WithMacKeyChain ( Constants . DefaultMsalTokenCacheKeychainService , name )
112101 . WithLinuxKeyring ( Constants . DefaultMsalTokenCacheKeyringSchema , Constants . DefaultMsalTokenCacheKeyringCollection , name , Constants . DefaultMsaltokenCacheKeyringAttribute1 , Constants . DefaultMsaltokenCacheKeyringAttribute2 )
113102 . Build ( ) ;
114103
115- MsalCacheHelper cacheHelper = await CreateCacheHelper ( async , storageProperties ) . ConfigureAwait( false) ;
116-
117- return cacheHelper;
118- }
119-
120- private static async Task < MsalCacheHelper > GetFallbackCacheHelperAsync ( bool async , CancellationToken cancellationToken )
121- {
122- using var asyncLock = await s_FallbackCacheHelperLock . GetLockOrValueAsync ( async , cancellationToken ) . ConfigureAwait( false) ;
123-
124- if ( asyncLock. HasValue)
125- {
126- return asyncLock. Value;
127- }
128-
129- MsalCacheHelper cacheHelper = await GetFallbackCacheHelperAsync ( async , Constants . DefaultMsalTokenCacheName ) . ConfigureAwait ( false ) ;
130-
131- asyncLock . SetValue ( cacheHelper ) ;
104+ MsalCacheHelperWrapper cacheHelper = await InitializeCacheHelper ( async , storageProperties ) . ConfigureAwait( false) ;
132105
133106 return cacheHelper;
134107 }
135108
136- private static async Task < MsalCacheHelper > GetFallbackCacheHelperAsync ( bool async , string name )
109+ private async Task < MsalCacheHelperWrapper > GetFallbackCacheHelperAsync ( bool async , string name = Constants . DefaultMsalTokenCacheName )
137110 {
138111 StorageCreationProperties storageProperties = new StorageCreationPropertiesBuilder ( name , Constants . DefaultMsalTokenCacheDirectory , s_msalCacheClientId )
139112 . WithMacKeyChain ( Constants . DefaultMsalTokenCacheKeychainService , name )
140113 . WithLinuxUnprotectedFile ( )
141114 . Build ( ) ;
142115
143- MsalCacheHelper cacheHelper = await CreateCacheHelper ( async , storageProperties ) . ConfigureAwait( false) ;
116+ MsalCacheHelperWrapper cacheHelper = await InitializeCacheHelper ( async , storageProperties ) . ConfigureAwait( false) ;
144117
145118 return cacheHelper;
146119 }
147120
148- private static async Task < MsalCacheHelper > CreateCacheHelper ( bool async , StorageCreationProperties storageProperties )
121+ private async Task < MsalCacheHelperWrapper > InitializeCacheHelper ( bool async , StorageCreationProperties storageProperties )
149122 {
150- return async
151- ? await MsalCacheHelper . CreateAsync ( storageProperties ) . ConfigureAwait ( false )
123+ if ( async)
124+ {
125+ await _cacheHelperWrapper . InitializeAsync ( storageProperties ) . ConfigureAwait ( false ) ;
126+ }
127+ else
128+ {
152129#pragma warning disable AZC0102 // Do not use GetAwaiter().GetResult(). Use the TaskExtensions.EnsureCompleted() extension method instead.
153- : MsalCacheHelper . CreateAsync ( storageProperties ) . GetAwaiter ( ) . GetResult ( ) ;
130+ _cacheHelperWrapper . InitializeAsync ( storageProperties ) . GetAwaiter ( ) . GetResult ( ) ;
154131#pragma warning restore AZC0102 // Do not use GetAwaiter().GetResult(). Use the TaskExtensions.EnsureCompleted() extension method instead.
132+ }
133+ return _cacheHelperWrapper;
155134 }
156135 }
157136}
0 commit comments