iOS ADAL - 使用刷新令牌进行静默调用

时间:2017-05-24 21:27:35

标签: ios iphone adal refresh-token msal

我正在使用iOS ADAL库版本2.2.6并在成功登录后接收刷新令牌。现在我想通过使用此刷新令牌进行静默调用。我尝试使用以下方法,但无法返回访问令牌。

 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."

有没有办法使用刷新令牌进行静默呼叫?请帮帮我。提前谢谢。

1 个答案:

答案 0 :(得分:4)

当您使用Microsoft的身份验证库时,您应该首先检查缓存中是否有用户可以在提示用户登录之前用于您的资源。这样我们就可以检查用户之前是否有用户登录到您的应用,或者是否有其他应用与您的应用共享状态可能已经要求用户在其他地方登录。

如果找到用户,我们将尝试获取令牌而不会中断用户。有时用户会更改密码或执行其他操作,即使他们之前已登录过您的应用,也需要他们再次登录。这就是你所看到的。 图书馆告诉您,对于您尝试获取令牌的用户,他们需要再次登录才能做出正确的事情。

为了优雅地处理所有这些情况,我们建议您使用伪代码模式:

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

模式首先检查您指定的用户是否在令牌缓存中可用。如果是,则我们调用Azure Active Directory服务以查看该用户的刷新令牌是否有效。如果这两个都为真,那么用户将以静默方式登录。如果未找到用户或服务器拒绝刷新令牌,则会从库发送错误,指示用户需要以交互方式登录。

在上文中,您正在执行此第一部分,但您没有处理用户在出现问题时需要登录的情况。

最好的方法是使用ADErrorCode AD_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]

调用单独的方法