2017-05-24 87 views
0

我正在使用iOS ADAL庫2.2.6版並在成功登錄後接收刷新令牌。現在我想通過使用此刷新令牌進行靜默調用。我嘗試使用下面的方法,但它無法返回訪問令牌。iOS ADAL-使用刷新令牌進行靜默呼叫

ADAuthenticationContext *authContext;    
[authContext acquireTokenSilentWithResource:resourceId 
            clientId:clientId 
            redirectUri:redirectUri 
             userId:strUserID //loggedIn userID 
           completionBlock:^(ADAuthenticationResult *result){ 

// It alway throws an error //Please call the non-silent acquireTokenWithResource methods. 
if(result.error){ 

ADAuthenticationError *error = nil; 
authContext = [ADAuthenticationContext authenticationContextWithAuthority:inputData.authority error:&error]; 

[authContext acquireTokenWithResource:inputData.ResourceID 
          clientId:inputData.ClientId       // Comes from App Portal 
          redirectUri:inputData.RedirectUri // Comes from App Portal 
         completionBlock:^(ADAuthenticationResult *result) 
{ 
    if (AD_SUCCEEDED != result.status){ 
     // Show alert with error description 
    } 
    else{ 

     //Handle Success token 
    } 
}]; 

}else{ 

     //Handle Success token 
} 

}]; 

但它總是拋出一個錯誤說"The user credentials are needed to obtain access token. Please call the non-silent acquireTokenWithResource methods."

有沒有什麼辦法讓使用刷新令牌無聲的電話嗎?請幫助我。提前致謝。

回答

3

當您使用Microsoft的身份驗證庫時,您應該首先檢查緩存中是否有用戶可以用於資源,然後再提示用戶登錄。這可以讓我們檢查用戶是否有先前已登錄您的應用,或者是否有其他與您的應用共享狀態的應用可能已經要求用戶在其他地方登錄。

如果找到用戶,我們將嘗試獲取令牌而不中斷用戶。有時用戶將更改密碼或執行其他操作,即使他們以前登錄過您的應用程序,也需要他們再次登錄。這就是你所看到的。 圖書館告訴你,對於試圖獲取令牌的用戶,他們需要再次登錄才能做出正確的決定。

爲了很好地處理所有這些情況下,我們建議您使用的僞模式:

acquireTokenSilent() 
(if error InteractiveAuthenticationRequired) { 
    acquireTokenInteractively() } 

模式先檢查是否指定了用戶在令牌緩存可用。如果是,我們然後調用Azure Active Directory服務來查看該用戶的Refresh標記是否有效。如果這兩個都是真的,那麼用戶就會默默登錄。如果未找到用戶或服務器拒絕刷新令牌,則會從庫中發送錯誤消息,指示用戶需要以交互方式登錄。

在上面,你正在做這第一部分,但你沒有處理用戶需要登錄的情況下,如果有問題。

的最佳方式是捕獲錯誤與ADErrorCodeAD_ERROR_USER_INPUT_NEEDED

這裏是如何做到這一點模式的代碼示例。

// Here we try to get a token from the stored user information we would have from a successful authentication 

    [authContext acquireTokenSilentWithResource:data.resourceId 
             clientId:data.clientId 
            redirectUri:redirectUri 
             userId:data.userItem.userInformation.userId 
           completionBlock:^(ADAuthenticationResult *result) { 
             if (!result.error) 
              { 

              completionBlock(result.tokenCacheStoreItem.userInformation, nil); 
             } else { 

               if ([result.error.domain isEqual:ADAuthenticationErrorDomain] && result.error.code == AD_ERROR_USER_INPUT_NEEDED) { 

                // Here we know that input is required because we couldn't get a token from the cache 

                [authContext acquireTokenWithResource:data.resourceId 
                       clientId:data.clientId 
                       redirectUri:redirectUri 
                        userId:data.userItem.userInformation.userId 
                      completionBlock:^(ADAuthenticationResult *result) { 

                       if (result.status != AD_SUCCEEDED) 
                       { 
                        completionBlock(nil, result.error); 
                       } 
                       else 
                       { 
                        data.userItem = result.tokenCacheStoreItem; 
                        completionBlock(result.tokenCacheStoreItem.userInformation, nil); 
                       } 
                      }]; 
               } else { 


                completionBlock(nil, result.error); 
               } 
             } 


           }]; 

請記住,這段代碼非常冗長。你很可能想要acquireTokenWithResource:一個單獨的方法,你可以撥打[self acquireTokenWithResource]

+0

感謝您的答覆。我會在今天檢查,意味着你可以看看我更新的問題(代碼)。 –

+0

上面的邏輯很好用。但訪問令牌在1小時後過期。因此,每次我們將服務調用爲「承載<訪問令牌>」時,我們是否在調用內部服務器調用之前調用上面的「acquireTokenSilentWithResource:」邏輯來獲取刷新令牌? –

+0

您應該嘗試調用API。如果您遇到訪問錯誤,則應調用acquireTokenSilentWithResource()。但是請記住,如果刷新令牌無效,會提示用戶。如果你不想這樣做(用戶正在做一些重要的事情,或者你可以等待提示他們),那麼在調用acquireToken()之前,你可能需要等待,所以你想以不同的方式處理錯誤。 –