iOS ADAL- совершите тихий звонок, используя токен обновления

Я использую библиотеку 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 ответ

Решение

Когда вы используете библиотеки аутентификации 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]

Другие вопросы по тегам