2016-11-07 35 views
2

我試圖使用Azure B2C和MSAL對用戶進行身份驗證,但遇到了一些用戶體驗問題。MSAL UserTokenCache未在Android上持久保存

當我調試我的應用程序時,我通常不必登錄,因爲我已經過身份驗證,令牌仍然有效。但是,如果我從Debug切換到Release,然後測試應用程序,AquireTokenSilentAsync方法似乎無法從UserTokenCache中檢索到有效的標記。我的假設是每次關閉應用程序時都會清除UserTokenCache。不知何故,這在調試模式下不會發生,我想這是因爲緩存在部署之間持續存在。

我以這種方式獲得驗證結果,但嘗試過不同的重載沒有任何成功。

AuthenticationResult AR =等待 App.PCApplication.AcquireTokenSilentAsync(App.Scopes, 「」, App.Authority,App.SignUpSignInpolicy,FALSE);

所以,當我登錄時,關閉並重新輸入應用程序,我仍然需要重新登錄。

我完全知道MSAL仍處於預覽狀態,但我一直未能找到與此行爲有關的任何問題。這是一個已知問題,是否有解決方法?

查看MSAL源代碼,我可以清楚地看到UserTokenCache正在使用Android SharePreferences進行持久保存,並且這在調試模式下可以很好地工作。所以,無論這是一個錯誤/缺少實現,或者我沒有看到明顯的東西..

+0

我已經做了一篇關於我在這裏弄清楚這個問題的博客文章:http://blog.wislon.io/posts/2016/12/05/msal-token-not-stored-on- android - 稍微不太詳細的版本作爲下面的潛在答案提供。 – wislon

回答

4

我能夠複製這幾乎完全。在IDE調試器下運行,它可以很好地工作,但如果它沒有連接到調試器,或者作爲發佈版本運行,它將默默無法存儲該令牌,並且嘗試持久性後的所有其他操作通常也無法運行。

我設法通過實現我自己的緩存來源於TokenCache並查看它試圖做什麼來解決Android上的這個相同問題。

我所在的例子爲一個桌面應用程序,如下所述:

https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-native-dotnet

,然後看了一下他們的FileCache因爲它是在他們的GitHub庫定義:

https://github.com/AzureADQuickStarts/B2C-NativeClient-DotNet/blob/complete/TaskClient/FileCache.cs

我複製了他們的FileCache,並將其添加到PublicClientApplication初始化:

ClientApplication = new PublicClientApplication(SharedConstants.AuthContext, SharedConstants.ClientId) 
{ 
    RedirectUri = "urn:ietf:wg:oauth:2.0:oob", 
    UserTokenCache = new FileCache(), 
}; 

(默認情況下,大多數示例將UserTokenCache屬性保留爲空,以推測使用平臺默認共享首選項)。

然後扭捏它做一些詳細的日誌記錄在讀/寫/只訪問,看看它是什麼達:

private void AfterAccessNotification(TokenCacheNotificationArgs args) 
{ 
    // if the access operation resulted in a cache update 
    try 
    { 
    this.Log().Debug("About to update token cache (if it's changed)..."); 
    if (this.HasStateChanged) 
    { 
     this.Log().Debug("State has changed, updating cache file..."); 
     lock (FileLock) 
     { 
     // reflect changes in the persistent store 
     _file.WriteAllBytes(CacheFilePath, this.Serialize()); 
     // once the write operation took place, restore the HasStateChanged bit to false 
     this.HasStateChanged = false; 
     } 
     this.Log().Debug("Token cache file updated"); 
    } 
    this.Log().Debug("Finished updating token cache file"); 
    } 
    catch (Exception ex) 
    { 
    this.Log().ErrorException($"Something went wrong during token AfterAccessNotification: {ex.Message}", ex); 
    } 
} 

的記錄顯示,在Android上,它被扔涉及有異常不是一個DateTimeOffset類型屬性的序列化處理程序,它位於MSAL庫的深處。

一旦我將AfterAccessNotification封裝在try-catch中並使用處理程序記錄發生了異常,它就完全開始工作。

我一直堅持使用這個版本的FileCache現在,因爲它大多解決了我目前的問題,但它確實意味着認證令牌等現在不能安全存儲。

我懷疑同樣的問題發生在模擬器上的iOS 10.x上,但我還沒有能夠驗證這一點。

我希望這可以幫助別人。

編輯:作爲@Henrik在他的評論中提到:編輯項目屬性,並告訴它到Android上System.Runtime.Serialization.dll鏈接,然後永久解決該問題。根據我的(公認的)有限的測試,可以安全地從使用FileCache再次轉換爲默認行爲。

+1

謝謝! TokenCache中的Serialize方法確實會引發異常:System.Runtime.Serialization.InvalidDataContractException:類型爲「System.Runtime.Serialization.DateTimeOffsetAdapter」的屬性'OffsetMinutes'沒有設置方法。有人建議跳過鏈接Android項目中的System.Runtime.Serialization程序集,這立即解決了這個問題。 –

+0

太棒了!你會願意還是能夠將此標記爲答案?顯然我不能自己做這個;) – wislon

+0

跳過「System.Runtime.Serializaton」的鏈接是否會給項目中的其他任何問題帶來任何其他問題?像任何不可行的情況,因爲這個跳過。謝謝 – Suchith