![](/img/trans.png)
[英]AcquireTokenSilent() throws Failed to acquire token silently. Call method AcquireToken error
[英]Azure - AD - AcquireTokenSilent giving error failed_to_acquire_token_silently
我們使用Azure AD進行身份驗證,並每隔30分鍾獲取刷新的訪問令牌。 我們調用以下方法獲取安全令牌並將其添加到請求頭。
var userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectId));
var credential = new ClientCredential(ConfigurationManager.AppSettings["ida:ClientId"],
ConfigurationManager.AppSettings["ida:ClientSecret"]);
try
{
var authenticationResult = authContext.AcquireTokenSilent(ConfigurationManager.AppSettings["WebAPIBaseAddress"], credential, new UserIdentifier(userObjectId, UserIdentifierType.UniqueId));
//set cookie for azure oauth refresh token - on successful login
var httpCookie = HttpContext.Current.Response.Cookies["RefreshToken"];
if (httpCookie != null)
httpCookie.Value = authenticationResult.RefreshToken;
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
}
catch
{
//Get access token using Refresh Token
var authenticationResult = authContext.AcquireTokenByRefreshToken(httpCookie.Value, credential, ConfigurationManager.AppSettings["WebAPIBaseAddress"]);
}
在上面的方法中,我們使用了AcquireTokenSilent方法,它為我們提供了訪問令牌。 由於訪問令牌僅持續一段時間。 到期后,我們調用AcquireTokenByRefreshToken來獲取刷新令牌。
上面的代碼運行良好,但我們隨機地得到以下異常:
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalSilentTokenAcquisitionException: Failed to acquire token silently. Call method AcquireToken
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenSilentHandler.SendTokenRequestAsync()
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<RunAsync>d__0.MoveNext()
ErrorCode: failed_to_acquire_token_silently
這種不一致的行為可能是什么原因? 相同的代碼在少數環境(Stage / Dev)上工作,但它在Production上隨機拋出錯誤。
請建議。
我們能夠解決這個問題。 這似乎是代碼本身的一個小錯誤。 當AccessToken到期時,它會拋出異常並嘗試使用catch塊中的AcquireTokenByRefreshToken獲取新的異常。 這里我們沒有在Cookie中設置新接收的刷新令牌。 我們還需要在catch塊中添加以下語句,以便它獲得Refresh標記,然后可以將其傳遞回以生成新的Access Token。
httpCookie.Value = authenticationResult.RefreshToken;
首先,在使用AcquireTokenSilent
之前,您必須調用AcquireTokenByAuthorizationCodeAsync
。
var context = new AuthenticationContext(authorityUri);
var credential = new ClientCredential(clientId, clientSecretKey);
await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, new Uri(redirectUri), credential);
AcquireTokenByAuthorizationCodeAsync
存儲訪問令牌和刷新令牌(對於從auth過程接收的用戶TokenCache.DefaultShared
)。
假設您這樣做,訪問令牌和刷新令牌確實會過期。 如果發生這種情況,您必須捕獲AdalSilentTokenAcquisitionException
異常:
try
{
// currentUser = new UserIdentifier() for: ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
AuthenticationResult authResult = await context.AcquireTokenSilentAsync(resourceUri, credential, currentUser);
return authResult.AccessToken;
}
catch (AdalSilentTokenAcquisitionException)
{
return null;
}
在每次請求資源之前調用此方法。 它沒有花費太多,理想情況下沒有,或者使用refreshToken命中oauth API。
但是當拋出AdalSilentTokenAcquisitionException
時(或者它是第一次調用)。 您必須調用從oauth API執行完全訪問代碼檢索的過程。 什么程序? 這取決於您正在使用的身份驗證過程的類型。
使用完整的owin auth,它可以是:
{"response_type", "code" }
重定向到權限uri HttpContext.GetOwinContext().Authentication.Challenge(OpenIdConnectAuthenticationDefaults.AuthenticationType);
(從控制器的操作返回null,因為Challenge()
方法改變HTTP響應以強制重定向到auth服務器)。 結束當前請求的處理(返回null)。 Auth服務器將使用新的授權代碼調用您的授權方法(來自UseOpenIdConnectAuthentication的通知的AuthorizationCodeReceived事件)。 稍后,重定向回需要令牌的原始頁面。 因此,您可能會收到AdalSilentTokenAcquisitionException,因為緩存已過期且refreshToken已過期。 您必須重新進行身份驗證(它是透明的,不需要登錄頁面)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.