簡體   English   中英

Azure - AD - AcquireTokenSilent給出錯誤failed_to_acquire_token_silently

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM