2015-04-20 107 views
9

使用ADAL我有兩個AuthenticationContext使用持久化在SQL中的令牌緩存。AcquireTokenSilent always無法無聲獲取令牌

使用AcquireTokenByAuthorizationCode它在數據庫中寫入令牌,但使用AcquireTokenSilent時,我總是得到

失敗默默獲得令牌。調用方法AcquireToken

下面是複製的細節問題:

我創建一個Context

AuthenticationContext authContext = new AuthenticationContext(_authority, new AzureAdalCache(companyId, _entries, _unitOfWork)); 

然後我AcquireToken通過授權

authContext.AcquireTokenByAuthorizationCode(authorizationCode, new Uri(redirectUri), _clientCredential); 

在這一點上,將條目保存在數據庫中

然後,如果我打電話給我,我會得到一個異常。

authContext.AcquireTokenSilent(_authority, _clientCredential, new UserIdentifier(companyId.ToString(), UserIdentifierType.UniqueId)).AccessToken; 

我也試過同樣的結果:

authContext.AcquireTokenSilent(_authority, _clientId).AccessToken; 
authContext.AcquireTokenSilent(_authority, _clientCredential, UserIdentifier.AnyUser).AccessToken; 

我發表我的this GistAzureAdalCache實施。

Cache的每個條目都是like this

我失蹤了什麼?

更新

基於對@vibronet的評論答案我有這個

AuthenticationContext authContext = new AuthenticationContext(_authority, new AzureAdalCache(companyId, _entries, _unitOfWork)); 
authContext.AcquireTokenByAuthorizationCode(authorizationCode, new Uri(redirectUri), _clientCredential, _eWSResource); 
string result = authContext.AcquireTokenSilent(_eWSResource, _clientId, UserIdentifier.AnyUser).AccessToken; 

回答

5

問題是,我基本上在我的應用程序中使用了Common Authority https://login.windows.net/common/oauth2/authorize。它適用於AcquireTokenByAuthorizationCode(),但不適用於AcquireTokenSilent()。

因此,當調用AcquireTokenByAuthorizationCode()時,我需要它來保存TenantId,並且在調用AcquireTokenSilent()時權限使用https://login.windows.net/<tenant ID>/oauth2/authorize這樣的權限。這樣上面的代碼就可以工作。

+0

另請注意,在ADAL的某些版本中,TenantId和用戶的UniqueId的GUID均爲大小寫因爲它們必須小寫才能使緩存正確加載它們。 – Andacious

+0

任何示例代碼都會有所幫助。因爲AcquireTokenByAuthorizationCodeAsync將有不同的參數。 – Kurkula

3

我不明白電話:

authContext.AcquireTokenSilent(
    _authority, 
    _clientCredential, 
    new UserIdentifier(companyId.ToString(), UserIdentifierType.UniqueId) 
).AccessToken; 

的UserIdentifier的必須的值相匹配在緩存中,並且CompanyID聽起來不像您爲令牌返回的任何標識符。

請看一看樣品我指出你給其他線程上,特別在https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet/blob/master/TodoListWebApp/Controllers/TodoListController.cs

在調用AcquireTokenSilent使用的標識符您不要選擇在呼叫使用的標識符,這是由AAD發佈的聲明決定的。唯一可以選擇的標識符是緩存實例級別,而不是單獨的AcquireToken *調用。

+1

謝謝@vibronet。我看到我做得很糟糕。 我應該使用 string userObjectID = ClaimsPrincipal.Current.FindFirst(「http://schemas.microsoft.com/identity/claims/objectidentifier」).Value; 但是...如何訪問後臺作業中的ClaimsPrincipal.Current?我得到「未將對象引用設置爲對象的實例」 –

+0

您必須在某處將他正確的值保存並傳遞給它:)或者如果要觸發按需邏輯 – vibronet

+0

但您必須公開Web API。 ..如果我沒有在我的網站上使用Azure身份驗證,我如何才能在網站上獲得索賠? 我的意思是,網站上的用戶是本地的應用程序(使用ASP.NET身份EntityFramework)。我允許用戶註冊他的天藍色AD作爲一些後臺工作,但我不會更改網站中的身份驗證和聲明。 因此,有什麼想法應該作爲UserId傳遞給AcquireTokenSilent()? –

0

檢查令牌在緩存中存在的其他登出,並要求用戶登錄

AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, 
         new NaiveSessionCache(userObjectID)); 
        if (authContext.TokenCache.Count == 0) 
        { 
         authContext.TokenCache.Clear(); 
         CosmosInterface.Utils.AuthenticationHelper.token = null; 
         HttpContext.GetOwinContext().Authentication.SignOut(
          OpenIdConnectAuthenticationDefaults.AuthenticationType, 
          CookieAuthenticationDefaults.AuthenticationType); 
        }