Skip to content

Commit 400842c

Browse files
authored
Merge pull request #5707 from twitchax/autosave_fix
Fix for Enable-AzureRmContextAutosave in Netcore (#5690).
2 parents 8b467df + 56a06a9 commit 400842c

File tree

2 files changed

+89
-40
lines changed

2 files changed

+89
-40
lines changed

src/Common/Commands.Common.Authentication/Authentication/ProtectedFileTokenCache.cs

Lines changed: 79 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -73,27 +73,7 @@ public ProtectedFileTokenCache(string cacheFile, IDataStore store = null)
7373

7474
private void Initialize(string fileName)
7575
{
76-
lock (fileLock)
77-
{
78-
if (_store.FileExists(fileName))
79-
{
80-
var existingData = _store.ReadFileAsBytes(fileName);
81-
if (existingData != null)
82-
{
83-
try
84-
{
85-
Deserialize(ProtectedData.Unprotect(existingData, null, DataProtectionScope.CurrentUser));
86-
}
87-
catch (CryptographicException)
88-
{
89-
_store.DeleteFile(fileName);
90-
}
91-
}
92-
}
93-
94-
// Create the file to start with
95-
_store.WriteFile(CacheFileName, ProtectedData.Protect(Serialize(), null, DataProtectionScope.CurrentUser));
96-
}
76+
EnsureCacheFile(fileName);
9777

9878
AfterAccess = AfterAccessNotification;
9979
BeforeAccess = BeforeAccessNotification;
@@ -113,45 +93,109 @@ public override void Clear()
11393
// Reload the cache from the persistent store in case it changed since the last access.
11494
void BeforeAccessNotification(TokenCacheNotificationArgs args)
11595
{
96+
ReadFileIntoCache();
97+
}
98+
99+
// Triggered right after ADAL accessed the cache.
100+
void AfterAccessNotification(TokenCacheNotificationArgs args)
101+
{
102+
// if the access operation resulted in a cache update
103+
EnsureStateSaved();
104+
}
105+
106+
void EnsureStateSaved()
107+
{
108+
if (HasStateChanged)
109+
{
110+
WriteCacheIntoFile();
111+
}
112+
}
113+
114+
private void ReadFileIntoCache(string cacheFileName = null)
115+
{
116+
if(cacheFileName == null)
117+
{
118+
cacheFileName = ProtectedFileTokenCache.CacheFileName;
119+
}
120+
116121
lock (fileLock)
117122
{
118-
if (_store.FileExists(CacheFileName))
123+
if (_store.FileExists(cacheFileName))
119124
{
120-
var existingData = _store.ReadFileAsBytes(CacheFileName);
125+
var existingData = _store.ReadFileAsBytes(cacheFileName);
121126
if (existingData != null)
122127
{
128+
#if !NETSTANDARD
123129
try
124130
{
125131
Deserialize(ProtectedData.Unprotect(existingData, null, DataProtectionScope.CurrentUser));
126132
}
127133
catch (CryptographicException)
128134
{
129-
_store.DeleteFile(CacheFileName);
135+
_store.DeleteFile(cacheFileName);
130136
}
137+
#else
138+
Deserialize(existingData);
139+
#endif
131140
}
132141
}
133142
}
134143
}
135144

136-
// Triggered right after ADAL accessed the cache.
137-
void AfterAccessNotification(TokenCacheNotificationArgs args)
145+
private void WriteCacheIntoFile(string cacheFileName = null)
138146
{
139-
// if the access operation resulted in a cache update
140-
EnsureStateSaved();
147+
if(cacheFileName == null)
148+
{
149+
cacheFileName = ProtectedFileTokenCache.CacheFileName;
150+
}
151+
152+
#if !NETSTANDARD
153+
var dataToWrite = ProtectedData.Protect(Serialize(), null, DataProtectionScope.CurrentUser);
154+
#else
155+
var dataToWrite = Serialize();
156+
#endif
157+
158+
lock(fileLock)
159+
{
160+
if (HasStateChanged)
161+
{
162+
_store.WriteFile(cacheFileName, dataToWrite);
163+
HasStateChanged = false;
164+
}
165+
}
141166
}
142167

143-
void EnsureStateSaved()
168+
private void EnsureCacheFile(string cacheFileName = null)
144169
{
145170
lock (fileLock)
146171
{
147-
if (HasStateChanged)
172+
if (_store.FileExists(cacheFileName))
148173
{
149-
// reflect changes in the persistent store
150-
_store.WriteFile(CacheFileName,
151-
ProtectedData.Protect(Serialize(), null, DataProtectionScope.CurrentUser));
152-
// once the write operation took place, restore the HasStateChanged bit to false
153-
HasStateChanged = false;
174+
var existingData = _store.ReadFileAsBytes(cacheFileName);
175+
if (existingData != null)
176+
{
177+
#if !NETSTANDARD
178+
try
179+
{
180+
Deserialize(ProtectedData.Unprotect(existingData, null, DataProtectionScope.CurrentUser));
181+
}
182+
catch (CryptographicException)
183+
{
184+
_store.DeleteFile(cacheFileName);
185+
}
186+
#else
187+
Deserialize(existingData);
188+
#endif
189+
}
154190
}
191+
192+
// Eagerly create cache file.
193+
#if !NETSTANDARD
194+
var dataToWrite = ProtectedData.Protect(Serialize(), null, DataProtectionScope.CurrentUser);
195+
#else
196+
var dataToWrite = Serialize();
197+
#endif
198+
_store.WriteFile(cacheFileName, dataToWrite);
155199
}
156200
}
157201
}

src/ServiceManagement/Services/Commands.Test/Profile/ProfileCmdltsTests.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,20 @@ public void ClearAzureProfileClearsTokenCache()
170170
[Trait(Category.AcceptanceType, Category.CheckIn)]
171171
public void DeleteCorruptedTokenCache()
172172
{
173-
//setup
173+
var corruptData = new byte[] { 0, 1 };
174+
174175
string testFileName = @"c:\foobar\TokenCache.dat";
175-
AzureSession.Instance.DataStore.WriteFile(testFileName, new byte[] { 0, 1 });
176+
AzureSession.Instance.DataStore.WriteFile(testFileName, corruptData);
176177

177-
//Act
178+
// Should delete the file because it is corrupt and create a "good" one.
178179
ProtectedFileTokenCache tokenCache = new ProtectedFileTokenCache(testFileName);
179180

180-
//Assert
181-
Assert.False(AzureSession.Instance.DataStore.FileExists(testFileName));
181+
// File should still exist because it was recreated.
182+
Assert.True(AzureSession.Instance.DataStore.FileExists(testFileName));
183+
#if !NETSTANDARD
184+
// But the data should not be the same when using DPAPI..
185+
Assert.NotEqual(corruptData, tokenCache.CacheData);
186+
#endif
182187
}
183188

184189
[Fact]

0 commit comments

Comments
 (0)