From 765dd8659a62a543cb3f3d31e13b756cc10896fd Mon Sep 17 00:00:00 2001 From: vibronet Date: Thu, 3 Jul 2014 14:46:05 -0700 Subject: [PATCH] Updated the client to the latest ADAL mostly changed the cache from CredMan to the new model against a DPAPI protected file --- TodoListClient/CacheHelper.cs | 225 ------------ TodoListClient/CredManCache.cs | 488 --------------------------- TodoListClient/FileCache.cs | 63 ++++ TodoListClient/MainWindow.xaml.cs | 12 +- TodoListClient/TodoListClient.csproj | 14 +- TodoListClient/packages.config | 2 +- 6 files changed, 78 insertions(+), 726 deletions(-) delete mode 100644 TodoListClient/CacheHelper.cs delete mode 100644 TodoListClient/CredManCache.cs create mode 100644 TodoListClient/FileCache.cs diff --git a/TodoListClient/CacheHelper.cs b/TodoListClient/CacheHelper.cs deleted file mode 100644 index bf09713..0000000 --- a/TodoListClient/CacheHelper.cs +++ /dev/null @@ -1,225 +0,0 @@ -//---------------------------------------------------------------------------------------------- -// Copyright 2014 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//---------------------------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -// The following using statements were added for this sample. -using Microsoft.IdentityModel.Clients.ActiveDirectory; - -namespace TodoListClient -{ - class TokenCacheKeyElements - { - public DateTimeOffset ExpiresOn { get; set; } - - public string Authority { get; set; } - public string ClientId { get; set; } - public string FamilyName { get; set; } - public string GivenName { get; set; } - public string IdentityProviderName { get; set; } - public string Resource { get; set; } - public string TenantId { get; set; } - public string UserId { get; set; } - - public bool IsMultipleResourceRefreshToken { get; set; } - public bool IsUserIdDisplayable { get; set; } - } - - enum TokenCacheKeyElement - { - Authority = 0, - ClientId = 1, - ExpiresOn = 2, - FamilyName = 3, - GivenName = 4, - IdentityProviderName = 5, - IsMultipleResourceRefreshToken = 6, - IsUserIdDisplayable = 7, - Resource = 8, - TenantId = 9, - UserId = 10 - } - - public class CacheHelper - { - private const string ElementDelimiter = ":"; - private const string SegmentDelimiter = "::"; - - public static string EncodeCacheKey(TokenCacheKey cacheKey) - { - var keyElements = new SortedDictionary(); - - keyElements[TokenCacheKeyElement.Authority] = cacheKey.Authority; - - if (!String.IsNullOrEmpty(cacheKey.Resource)) - { - keyElements[TokenCacheKeyElement.Resource] = cacheKey.Resource; - } - - if (!String.IsNullOrEmpty(cacheKey.ClientId)) - { - keyElements[TokenCacheKeyElement.ClientId] = cacheKey.ClientId; - } - - if (null != cacheKey.ExpiresOn) - { - keyElements[TokenCacheKeyElement.ExpiresOn] = cacheKey.ExpiresOn.ToString(); - } - - if (!String.IsNullOrEmpty(cacheKey.FamilyName)) - { - keyElements[TokenCacheKeyElement.FamilyName] = cacheKey.FamilyName; - } - - if (!String.IsNullOrEmpty(cacheKey.GivenName)) - { - keyElements[TokenCacheKeyElement.GivenName] = cacheKey.GivenName; - } - - if (!String.IsNullOrEmpty(cacheKey.IdentityProviderName)) - { - keyElements[TokenCacheKeyElement.IdentityProviderName] = cacheKey.IdentityProviderName; - } - - if (false != cacheKey.IsMultipleResourceRefreshToken) - { - keyElements[TokenCacheKeyElement.IsMultipleResourceRefreshToken] = cacheKey.IsMultipleResourceRefreshToken.ToString(); - } - - if (false != cacheKey.IsUserIdDisplayable) - { - keyElements[TokenCacheKeyElement.IsUserIdDisplayable] = cacheKey.IsUserIdDisplayable.ToString(); - } - - if (!String.IsNullOrEmpty(cacheKey.TenantId)) - { - keyElements[TokenCacheKeyElement.TenantId] = cacheKey.TenantId; - } - - if (!String.IsNullOrEmpty(cacheKey.UserId)) - { - keyElements[TokenCacheKeyElement.UserId] = cacheKey.UserId; - } - - return CreateFromKeyElements(keyElements); - } - - internal static string CreateFromKeyElements(SortedDictionary keyElements) - { - if (keyElements == null) - { - throw new ArgumentNullException("keyElements"); - } - - string keyHeader = String.Join(ElementDelimiter, keyElements.Keys.Select(k => (int)k)); - string keyContent = String.Join(ElementDelimiter, keyElements.Values.Select(Base64Encode)); - return CreateKey(keyHeader, keyContent); - } - - private static string CreateKey(string keyHeader, string keyContent) - { - return String.Join( - SegmentDelimiter, - new[] { Base64Encode(keyHeader), Base64Encode(keyContent) }); - } - - internal static string Base64Encode(string input) - { - string encodedString = String.Empty; - - if (!String.IsNullOrEmpty(input)) - { - encodedString = Convert.ToBase64String(Encoding.UTF8.GetBytes(input)); - } - - return encodedString; - } - - internal static string Base64Decode(string encodedString) - { - string output = null; - - if (!String.IsNullOrEmpty(encodedString)) - { - byte[] outputBytes = Convert.FromBase64String(encodedString); - output = Encoding.UTF8.GetString(outputBytes, 0, outputBytes.Length); - } - - return output; - } - - public static TokenCacheKey DecodeCacheKey(string cacheKey) - { - var elements = new TokenCacheKey(); - IDictionary elementDictionary = Decode(cacheKey); - elements.Authority = elementDictionary.ContainsKey(TokenCacheKeyElement.Authority) ? elementDictionary[TokenCacheKeyElement.Authority] : null; - elements.ClientId = elementDictionary.ContainsKey(TokenCacheKeyElement.ClientId) ? elementDictionary[TokenCacheKeyElement.ClientId] : null; - elements.FamilyName = elementDictionary.ContainsKey(TokenCacheKeyElement.FamilyName) ? elementDictionary[TokenCacheKeyElement.FamilyName] : null; - elements.GivenName = elementDictionary.ContainsKey(TokenCacheKeyElement.GivenName) ? elementDictionary[TokenCacheKeyElement.GivenName] : null; - elements.IdentityProviderName = elementDictionary.ContainsKey(TokenCacheKeyElement.IdentityProviderName) ? elementDictionary[TokenCacheKeyElement.IdentityProviderName] : null; - elements.Resource = elementDictionary.ContainsKey(TokenCacheKeyElement.Resource) ? elementDictionary[TokenCacheKeyElement.Resource] : null; - elements.TenantId = elementDictionary.ContainsKey(TokenCacheKeyElement.TenantId) ? elementDictionary[TokenCacheKeyElement.TenantId] : null; - elements.UserId = elementDictionary.ContainsKey(TokenCacheKeyElement.UserId) ? elementDictionary[TokenCacheKeyElement.UserId] : null; - - if (elementDictionary.ContainsKey(TokenCacheKeyElement.ExpiresOn)) - { - elements.ExpiresOn = DateTimeOffset.Parse(elementDictionary[TokenCacheKeyElement.ExpiresOn]); - } - - if (elementDictionary.ContainsKey(TokenCacheKeyElement.IsUserIdDisplayable)) - { - elements.IsUserIdDisplayable = bool.Parse(elementDictionary[TokenCacheKeyElement.IsUserIdDisplayable]); - } - - if (elementDictionary.ContainsKey(TokenCacheKeyElement.IsMultipleResourceRefreshToken)) - { - elements.IsMultipleResourceRefreshToken = bool.Parse(elementDictionary[TokenCacheKeyElement.IsMultipleResourceRefreshToken]); - } - - return elements; - } - - internal static Dictionary Decode(string cacheKey) - { - string[] keySegments = cacheKey.Split(new[] { SegmentDelimiter }, StringSplitOptions.None); - - if (keySegments.Length != 2) - { - throw new ArgumentException("invalid key format", "key"); - } - - string[] headerElements = Base64Decode(keySegments[0]).Split(new[] { ElementDelimiter }, StringSplitOptions.None); - string[] contentElements = Base64Decode(keySegments[1]).Split(new[] { ElementDelimiter }, StringSplitOptions.None); - - if (headerElements.Length != contentElements.Length) - { - throw new ArgumentException("iunvalid key format", "key"); - } - - var keyElementDictionary = new Dictionary(); - for (int i = 0; i < headerElements.Length; i++) - { - keyElementDictionary.Add((TokenCacheKeyElement)Enum.Parse(typeof(TokenCacheKeyElement), headerElements[i]), Base64Decode(contentElements[i])); - } - - return keyElementDictionary; - } - } -} diff --git a/TodoListClient/CredManCache.cs b/TodoListClient/CredManCache.cs deleted file mode 100644 index 656cde9..0000000 --- a/TodoListClient/CredManCache.cs +++ /dev/null @@ -1,488 +0,0 @@ -//---------------------------------------------------------------------------------------------- -// Copyright 2014 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//---------------------------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -// The following using statements were added for this sample. -using Microsoft.IdentityModel.Clients.ActiveDirectory; -using System.Runtime.InteropServices; -using System.Runtime.ConstrainedExecution; - -namespace TodoListClient -{ - class CredManCache : IDictionary - { - const int oneKB = 1024; - public const string UniqueApplicationString = "todoListClientAdalDotNet"; - - public void Add(TokenCacheKey cacheKey, string value) - { - // encode the cacheKey into a string - string key = CacheHelper.EncodeCacheKey(cacheKey); - - // Split the value into 1K bytes length pieces into order to comply with the CredMan size limit on the (Credential Blob) size. - List splitValues = Split(value); - - int count = 0; - - // Add an entry it CredMan for each 1K byte length string. - foreach (string val in splitValues) - { - // Key each string with the key ending with "-0", "-1" and so on... - AddCacheEntry(key + "-" + count, val); - count++; - } - } - - public void Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - public bool ContainsKey(TokenCacheKey key) - { - string value; - return TryGetValue(key, out value); - } - - public void Clear() - { - int count; - IntPtr list; - - // Get the count and a pointer to the list of entries in CredMan. - if (NativeMethods.CredEnumerate(null, 0, out count, out list)) - { - try - { - for (int i = 0; i < count; i++) - { - IntPtr pCredential = Marshal.ReadIntPtr(list, i * Marshal.SizeOf(typeof(IntPtr))); - NativeMethods.Credential cred = (NativeMethods.Credential)Marshal.PtrToStructure(pCredential, typeof(NativeMethods.Credential)); - IntPtr credential; - - // check if the entry was created by this application by checking the userName and making sure that this application can Read the entry - if (cred.userName == UniqueApplicationString && NativeMethods.CredRead(cred.targetName, CredentialType.Generic, 0, out credential)) - { - try - { - // Call CredDelete to delete the entry in CredMan. - NativeMethods.CredDelete(cred.targetName, CredentialType.Generic, 0); - } - finally - { - NativeMethods.CredFree(credential); - } - } - - } - } - finally - { - NativeMethods.CredFree(list); - } - } - } - - public bool Contains(KeyValuePair item) - { - string value; - - TryGetValue(item.Key, out value); - - if (value != null) - { - return (value.Equals(item.Value)); - } - return false; - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public int Count - { - get { return Keys.Count; } - } - - public IEnumerator> GetEnumerator() - { - foreach (TokenCacheKey key in this.Keys) - { - yield return new KeyValuePair(key, this[key]); - } - } - - public ICollection Keys - { - get - { - int count; - IntPtr list; - HashSet keysSet = new HashSet(); - - // Get the count and a pointer to the list of entries in CredMan. - if (NativeMethods.CredEnumerate(null, 0, out count, out list)) - { - try - { - for (int i = 0; i < count; i++) - { - IntPtr pCredential = Marshal.ReadIntPtr(list, i * Marshal.SizeOf(typeof(IntPtr))); - NativeMethods.Credential credential = (NativeMethods.Credential)Marshal.PtrToStructure(pCredential, typeof(NativeMethods.Credential)); - - IntPtr cred; - - // check if the credential was created by this application. - if (credential.userName == UniqueApplicationString && NativeMethods.CredRead(credential.targetName, CredentialType.Generic, 0, out cred)) - { - try - { - // add the key (removing the suffix of -count, ex: -0, -1 etc. that were added in Add()) to the set of keys. - keysSet.Add(credential.targetName.Substring(0, credential.targetName.Length - 2)); - } - - finally - { - NativeMethods.CredFree(cred); - } - } - } - } - finally - { - NativeMethods.CredFree(list); - } - } - - List keys = new List(); - - foreach (string k in keysSet) - { - keys.Add(CacheHelper.DecodeCacheKey(k)); - } - - return keys; - } - } - - public bool Remove(TokenCacheKey cacheKey) - { - int count; - IntPtr list; - - string key = CacheHelper.EncodeCacheKey(cacheKey); - - // Get the count and a pointer to the list of entries whose targetName starts with "key" in CredMan. - if (NativeMethods.CredEnumerate(key + "*", 0, out count, out list)) - { - try - { - for (int i = 0; i < count; i++) - { - IntPtr pCredential = Marshal.ReadIntPtr(list, i * Marshal.SizeOf(typeof(IntPtr))); - NativeMethods.Credential credential = (NativeMethods.Credential)Marshal.PtrToStructure(pCredential, typeof(NativeMethods.Credential)); - - // Delete the entry. - NativeMethods.CredDelete(credential.targetName, CredentialType.Generic, 0); - } - } - finally - { - NativeMethods.CredFree(list); - } - return true; - } - - return false; - } - - public bool Remove(KeyValuePair item) - { - if (this.Contains(item)) - { - this.Remove(item.Key); - return true; - } - return false; - } - - public bool TryGetValue(TokenCacheKey cacheKey, out string value) - { - value = null; - - int count; - IntPtr list; - IntPtr pCredential; - - string key = CacheHelper.EncodeCacheKey(cacheKey); - - // Get the count and a pointer to the list of entries whose targetName (key) begins with "key" - - if (NativeMethods.CredEnumerate(key + '*', 0, out count, out list)) - { - try - { - Dictionary values = new Dictionary(); - - for (int i = 0; i < count; i++) - { - // Read the Credential, only get the entries created by CredMan. - if (NativeMethods.CredRead(key + "-" + i, CredentialType.Generic, 0, out pCredential)) - { - try - { - NativeMethods.Credential cred = (NativeMethods.Credential)Marshal.PtrToStructure(pCredential, typeof(NativeMethods.Credential)); - - // Add the value to the list of values. - values.Add(cred.targetName, Marshal.PtrToStringUni(cred.credentialBlob, (int)(cred.credentialBlobSize - 1) / 2)); - } - finally - { - NativeMethods.CredFree(pCredential); - } - } - } - - // Stitch together the values to get the value, since they were split up during Add() - value = Merge(values); - - if (!string.IsNullOrEmpty(value)) - { - return true; - } - } - finally - { - NativeMethods.CredFree(list); - } - } - - return false; - } - - public ICollection Values - { - get - { - List values = new List(); - - foreach (TokenCacheKey key in Keys) - { - values.Add(this[key]); - } - - return values; - } - } - - public string this[TokenCacheKey key] - { - get - { - string value = null; - TryGetValue(key, out value); - return value; - } - set - { - Add(key, value); - } - } - - public bool IsReadOnly - { - get { return false; } - } - - private void AddCacheEntry(string key, string value) - { - // Create a Credential to represent an entry in CredMan - NativeMethods.Credential credential = new NativeMethods.Credential(key, value); - - int size = Marshal.SizeOf(credential); - IntPtr ptr = Marshal.AllocHGlobal(size); - try - { - Marshal.StructureToPtr(credential, ptr, false); - if (!NativeMethods.CredWrite(ptr, 0)) - { - throw new Exception("Exception occurred while writing to cache. Error Code : " + Marshal.GetLastWin32Error()); - } - } - finally - { - Marshal.FreeHGlobal(ptr); - } - } - - /// - /// Splits a given string into substrings of 1KB length each, except the last substring which could be lesser than 1KB length - /// - List Split(string s) - { - List list = new List(); - - int length = s.Length; - int index = 0; - - while (length > oneKB) - { - // Get a 1 KB length substring and add it to the list - list.Add(s.Substring(index, oneKB)); - index += oneKB; - length -= oneKB; - } - - // Add the remaining substring to the list. - list.Add(s.Substring(index)); - - return list; - } - - /// - /// Takes in a list of key, value pairs and stitches the values together and returns the stitched together value. - /// - string Merge(Dictionary items) - { - string combinedValue = string.Empty; - string value; - - int count = items.Count; - string key = string.Empty; - - key = items.Keys.First(); - - if (string.IsNullOrEmpty(key)) - { - return null; - } - - // prune off the -digit suffix in the end. - key = key.Substring(0, key.Length - 2); - - // combine the values - for (int i = 0; i < count; i++) - { - // get the keys in the order of increasing suffix digits in the end. - if (items.TryGetValue(key + "-" + i, out value)) - { - combinedValue += value; - } - } - - return combinedValue; - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return (IEnumerator>)GetEnumerator(); - } - } - - enum CredentialType - { - Generic = 1, - } - - class NativeMethods - { - [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal extern static bool CredRead( - string targetName, - CredentialType type, - int flags, - [Out] out IntPtr pCredential - ); - - [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal extern static bool CredEnumerate( - string targetName, - int flags, - [Out] out int count, - [Out] out IntPtr pCredential - ); - - [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal extern static bool CredDelete( - string targetName, - CredentialType type, - int flags - ); - - [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal extern static bool CredWrite( - IntPtr pCredential, - int flags - ); - - [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] - internal extern static bool CredFree( - IntPtr pCredential - ); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct Credential - { - public Credential(string key, string value) - { - this.flags = 0; - this.type = CredentialType.Generic; - - // set the key in the targetName - this.targetName = key; - - this.targetAlias = null; - this.comment = null; - this.lastWritten.dwHighDateTime = 0; - this.lastWritten.dwLowDateTime = 0; - - // set the value in credentialBlob. - this.credentialBlob = Marshal.StringToHGlobalUni(value); - this.credentialBlobSize = (uint)((value.Length + 1) * 2); - - this.persist = 1; - this.attibuteCount = 0; - this.attributes = IntPtr.Zero; - this.userName = CredManCache.UniqueApplicationString; - } - - internal uint flags; - internal CredentialType type; - internal string targetName; - internal string comment; - internal System.Runtime.InteropServices.ComTypes.FILETIME lastWritten; - internal uint credentialBlobSize; - internal IntPtr credentialBlob; - internal uint persist; - internal uint attibuteCount; - internal IntPtr attributes; - internal string targetAlias; - internal string userName; - } - } -} diff --git a/TodoListClient/FileCache.cs b/TodoListClient/FileCache.cs new file mode 100644 index 0000000..821ff95 --- /dev/null +++ b/TodoListClient/FileCache.cs @@ -0,0 +1,63 @@ +using Microsoft.IdentityModel.Clients.ActiveDirectory; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Security.Cryptography; + +namespace TodoListClient +{ + class FileCache : TokenCache + { + public string CacheFilePath; + private static readonly object FileLock = new object(); + + // Initializes the cache against a local file. + // If the file is already rpesent, it loads its content in the ADAL cache + public FileCache(string filePath = @".\TokenCache.dat") + { + CacheFilePath = filePath; + this.AfterAccess = AfterAccessNotification; + this.BeforeAccess = BeforeAccessNotification; + lock (FileLock) + { + this.Deserialize(File.Exists(CacheFilePath) ? ProtectedData.Unprotect(File.ReadAllBytes(CacheFilePath), null, DataProtectionScope.CurrentUser) : null); + } + } + + // Empties the persistent store. + public override void Clear() + { + base.Clear(); + File.Delete(CacheFilePath); + } + + // Triggered right before ADAL needs to access the cache. + // Reload the cache from the persistent store in case it changed since the last access. + void BeforeAccessNotification(TokenCacheNotificationArgs args) + { + lock (FileLock) + { + this.Deserialize(File.Exists(CacheFilePath) ? ProtectedData.Unprotect(File.ReadAllBytes(CacheFilePath), null, DataProtectionScope.CurrentUser) : null); + } + } + + // Triggered right after ADAL accessed the cache. + void AfterAccessNotification(TokenCacheNotificationArgs args) + { + // if the access operation resulted in a cache update + if (this.HasStateChanged) + { + lock (FileLock) + { + // reflect changes in the persistent store + File.WriteAllBytes(CacheFilePath, ProtectedData.Protect(this.Serialize(), null, DataProtectionScope.CurrentUser)); + // once the write operation took place, restore the HasStateChanged bit to false + this.HasStateChanged = false; + } + } + } + } +} diff --git a/TodoListClient/MainWindow.xaml.cs b/TodoListClient/MainWindow.xaml.cs index f4a5bb7..a59ac7b 100644 --- a/TodoListClient/MainWindow.xaml.cs +++ b/TodoListClient/MainWindow.xaml.cs @@ -76,7 +76,7 @@ public MainWindow() // // As the application starts, try to get an access token without prompting the user. If one exists, populate the To Do list. If not, continue. // - authContext = new AuthenticationContext(authority, new CredManCache()); + authContext = new AuthenticationContext(authority, new FileCache()); AuthenticationResult result = null; try { @@ -86,7 +86,7 @@ public MainWindow() SignInButton.Content = "Clear Cache"; GetTodoList(); } - catch (ActiveDirectoryAuthenticationException ex) + catch (AdalException ex) { if (ex.ErrorCode == "user_interaction_required") { @@ -117,7 +117,7 @@ private async void GetTodoList() { result = authContext.AcquireToken(todoListResourceId, clientId, redirectUri, PromptBehavior.Never); } - catch (ActiveDirectoryAuthenticationException ex) + catch (AdalException ex) { // There is no access token in the cache, so prompt the user to sign-in. if (ex.ErrorCode == "user_interaction_required") @@ -179,7 +179,7 @@ private async void AddTodoItem(object sender, RoutedEventArgs e) { result = authContext.AcquireToken(todoListResourceId, clientId, redirectUri, PromptBehavior.Never); } - catch (ActiveDirectoryAuthenticationException ex) + catch (AdalException ex) { // There is no access token in the cache, so prompt the user to sign-in. if (ex.ErrorCode == "user_interaction_required") @@ -232,7 +232,7 @@ private void SignIn(object sender = null, RoutedEventArgs args = null) if (SignInButton.Content.ToString() == "Clear Cache") { TodoList.ItemsSource = string.Empty; - authContext.TokenCacheStore.Clear(); + authContext.TokenCache.Clear(); // Also clear cookies from the browser control. ClearCookies(); SignInButton.Content = "Sign In"; @@ -249,7 +249,7 @@ private void SignIn(object sender = null, RoutedEventArgs args = null) SignInButton.Content = "Clear Cache"; GetTodoList(); } - catch (ActiveDirectoryAuthenticationException ex) + catch (AdalException ex) { if (ex.ErrorCode == "authentication_canceled") { diff --git a/TodoListClient/TodoListClient.csproj b/TodoListClient/TodoListClient.csproj index 6a718a1..490fd0a 100644 --- a/TodoListClient/TodoListClient.csproj +++ b/TodoListClient/TodoListClient.csproj @@ -34,16 +34,19 @@ 4 - - ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.3\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.dll + + False + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.7.10703-alpha\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll - - ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.3\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll + + False + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.7.10703-alpha\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll + @@ -62,6 +65,7 @@ MSBuild:Compile Designer + MSBuild:Compile @@ -71,8 +75,6 @@ App.xaml Code - - MainWindow.xaml Code diff --git a/TodoListClient/packages.config b/TodoListClient/packages.config index 2ea651c..e6902c6 100644 --- a/TodoListClient/packages.config +++ b/TodoListClient/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file