12
12
// limitations under the License.
13
13
// ----------------------------------------------------------------------------------
14
14
15
+ using Hyak . Common ;
15
16
using Microsoft . Azure . Commands . Common . Authentication . Abstractions ;
16
17
using Microsoft . Azure . Commands . Common . Authentication . Properties ;
17
18
using Microsoft . IdentityModel . Clients . ActiveDirectory ;
18
19
using System ;
19
20
using System . IO ;
20
21
using System . Security . Cryptography ;
22
+ using System . Threading ;
21
23
22
24
#if NETSTANDARD
23
25
namespace Microsoft . Azure . Commands . Common . Authentication . Core
@@ -41,7 +43,10 @@ public class ProtectedFileTokenCache : TokenCache, IAzureTokenCache
41
43
#endif
42
44
"TokenCache.dat" ) ;
43
45
44
- private static readonly object fileLock = new object ( ) ;
46
+ /// <summary>
47
+ /// A mutex to prevent IO to token cache file across threads / processes.
48
+ /// </summary>
49
+ private static readonly Mutex fileLock = new Mutex ( false , @"Global\AzurePowerShellAdalTokenCacheFile" ) ;
45
50
46
51
private static readonly Lazy < ProtectedFileTokenCache > instance = new Lazy < ProtectedFileTokenCache > ( ( ) => new ProtectedFileTokenCache ( ) ) ;
47
52
@@ -123,38 +128,37 @@ void EnsureStateSaved()
123
128
124
129
private void ReadFileIntoCache ( string cacheFileName = null )
125
130
{
126
- if ( cacheFileName == null )
131
+ if ( cacheFileName == null )
127
132
{
128
133
cacheFileName = ProtectedFileTokenCache . CacheFileName ;
129
134
}
130
135
131
- lock ( fileLock )
136
+ fileLock . WaitOne ( ) ;
137
+ if ( _store . FileExists ( cacheFileName ) )
132
138
{
133
- if ( _store . FileExists ( cacheFileName ) )
139
+ var existingData = _store . ReadFileAsBytes ( cacheFileName ) ;
140
+ if ( existingData != null )
134
141
{
135
- var existingData = _store . ReadFileAsBytes ( cacheFileName ) ;
136
- if ( existingData != null )
137
- {
138
142
#if ! NETSTANDARD
139
- try
140
- {
141
- Deserialize ( ProtectedData . Unprotect ( existingData , null , DataProtectionScope . CurrentUser ) ) ;
142
- }
143
- catch ( CryptographicException )
144
- {
145
- _store . DeleteFile ( cacheFileName ) ;
146
- }
143
+ try
144
+ {
145
+ Deserialize ( ProtectedData . Unprotect ( existingData , null , DataProtectionScope . CurrentUser ) ) ;
146
+ }
147
+ catch ( CryptographicException )
148
+ {
149
+ _store . DeleteFile ( cacheFileName ) ;
150
+ }
147
151
#else
148
- Deserialize ( existingData ) ;
152
+ Deserialize ( existingData ) ;
149
153
#endif
150
- }
151
154
}
152
155
}
156
+ fileLock . ReleaseMutex ( ) ;
153
157
}
154
158
155
159
private void WriteCacheIntoFile ( string cacheFileName = null )
156
160
{
157
- if ( cacheFileName == null )
161
+ if ( cacheFileName == null )
158
162
{
159
163
cacheFileName = ProtectedFileTokenCache . CacheFileName ;
160
164
}
@@ -165,25 +169,23 @@ private void WriteCacheIntoFile(string cacheFileName = null)
165
169
var dataToWrite = Serialize ( ) ;
166
170
#endif
167
171
168
- lock ( fileLock )
172
+ fileLock . WaitOne ( ) ;
173
+ if ( HasStateChanged )
169
174
{
170
- if ( HasStateChanged )
171
- {
172
- _store . WriteFile ( cacheFileName , dataToWrite ) ;
173
- HasStateChanged = false ;
174
- }
175
+ _store . WriteFile ( cacheFileName , dataToWrite ) ;
176
+ HasStateChanged = false ;
175
177
}
178
+ fileLock . ReleaseMutex ( ) ;
176
179
}
177
180
178
181
private void EnsureCacheFile ( string cacheFileName = null )
179
182
{
180
- lock ( fileLock )
183
+ fileLock . WaitOne ( ) ;
184
+ if ( _store . FileExists ( cacheFileName ) )
181
185
{
182
- if ( _store . FileExists ( cacheFileName ) )
186
+ var existingData = _store . ReadFileAsBytes ( cacheFileName ) ;
187
+ if ( existingData != null )
183
188
{
184
- var existingData = _store . ReadFileAsBytes ( cacheFileName ) ;
185
- if ( existingData != null )
186
- {
187
189
#if ! NETSTANDARD
188
190
try
189
191
{
@@ -194,19 +196,19 @@ private void EnsureCacheFile(string cacheFileName = null)
194
196
_store . DeleteFile ( cacheFileName ) ;
195
197
}
196
198
#else
197
- Deserialize ( existingData ) ;
199
+ Deserialize ( existingData ) ;
198
200
#endif
199
- }
200
201
}
202
+ }
201
203
202
- // Eagerly create cache file.
204
+ // Eagerly create cache file.
203
205
#if ! NETSTANDARD
204
206
var dataToWrite = ProtectedData . Protect ( Serialize ( ) , null , DataProtectionScope . CurrentUser ) ;
205
207
#else
206
- var dataToWrite = Serialize ( ) ;
208
+ var dataToWrite = Serialize ( ) ;
207
209
#endif
208
- _store . WriteFile ( cacheFileName , dataToWrite ) ;
209
- }
210
+ _store . WriteFile ( cacheFileName , dataToWrite ) ;
211
+ fileLock . ReleaseMutex ( ) ;
210
212
}
211
213
}
212
214
}
0 commit comments