2016-07-08 4 views
1

Я пишу простое настольное приложение, которое должно получить некоторые основные свойства пользователя из каталога Microsoft. В частности:Простой поиск каталога в Azure Active Directory

  1. Я пишу одно приложение LOB для местного арендатора.
  2. Приложение работает на моем рабочем столе.
  3. Приложение работает как зарегистрированная учетная запись домена.
  4. Учетные записи домена организации синхронизируются с AAD.
  5. Я не пытаюсь защитить собственное веб-приложение или веб-API или что-то в этом роде. Мне не нужны пользователи для входа.
  6. У меня есть адреса электронной почты людей в моей организации из внешнего инструмента управления событиями. Мне нужно найти данные профиля учетной записи AAD (адресная книга - определенная должность) из AAD на основе адреса электронной почты. Я буду читать только данные AAD.

До сих пор, я сделал следующее: -

  1. Оказывается, что Azure AD Graph API является правильным способом для извлечения информации о профиле. В частности, информация доступна на конечной точке: https://graph.windows.net/ {арендатор}/users/{email}? Api-version = 1.6

  2. При регистрации собственного приложения в AAD ключ не был предоставлен. Поэтому у меня нет секретности клиента.

  3. Посмотрите на образец в GitHub здесь: https://github.com/Azure-Samples/active-directory-dotnet-graphapi-console. Инструкции здесь кажутся неправильными, потому что нет раздела «Ключи» [см. (2)].

Основываясь на примере выше, я написал простую функцию. Код ниже:

private static async Task PrintAADUserData(string email) 
    { 
     string clientId = "0a202b2c-6220-438d-9501-036d4e05037f"; 
     Uri redirectUri = new Uri("http://localhost:4000"); 
     string resource = "https://graph.windows.net/{tenant}"; 
     string authority = "https://login.microsoftonline.com/{tenant}/oauth2/authorize"; 
     AuthenticationContext authContext = new AuthenticationContext(authority); 

     AuthenticationResult authResult = await authContext.AcquireTokenAsync(resource, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto)); 

     string api = String.Format("https://graph.windows.net/{tenant}/users/{0}?api-version=1.6", email); 
     LOG.DebugFormat("Using API URL {0}", api); 

     // Create an HTTP client and add the token to the Authorization header 
     HttpClient httpClient = new HttpClient(); 
     httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authResult.AccessTokenType, authResult.AccessToken); 
     HttpResponseMessage response = await httpClient.GetAsync(api); 

     string data = await response.Content.ReadAsStringAsync(); 
     LOG.Debug(data); 
    } 

Вопросы

  1. Применение при запуске удалось открыть страницу аутентификации. Зачем мне это нужно? Приложение уже работает как моя учетная запись домена. Требуется ли дополнительная проверка подлинности? Если бы я запускал это приложение в Azure в качестве рабочего процесса, я бы не захотел использовать свои учетные данные домена.

  2. Первичной проблемой является URL-адрес ресурса, который является неправильным. Какой ресурс мне нужно указать для доступа к API-интерфейсу Azure AD?

Спасибо,

Виджай.

редактирует

На основе комментариев от @Saca, код и приложение было отредактировано.

код

string clientId = ConfigurationManager.AppSettings["AADClientId"]; 
string clientSecret = ConfigurationManager.AppSettings["AADClientSecret"]; 
string appIdUri = ConfigurationManager.AppSettings["AADAppIdURI"]; 
string authEndpoint = ConfigurationManager.AppSettings["AADGraphAuthority"]; 
string graphEndpoint = ConfigurationManager.AppSettings["AADGraphEndpoint"]; 

AuthenticationContext authContext = new AuthenticationContext(authEndpoint, false); 
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.windows.net", new ClientCredential(clientId, clientSecret)); 
ExistingTokenWrapper wrapper = new ExistingTokenWrapper(authResult.AccessToken); 
ActiveDirectoryClient client = new ActiveDirectoryClient(new Uri(graphEndpoint), async() => await wrapper.GetToken()); 

IUser user = client.Users.Where(_ => _.UserPrincipalName.Equals(email.ToLowerInvariant())).Take(1).ExecuteSingleAsync().Result; 

App AAD Application Permissions Setup Ошибка Необработанное исключение: System.AggregateException: Произошла одна или несколько ошибок. ---> System.AggregateException: произошла одна или несколько ошибок. ---> Microsoft.Data.OData.ODataErrorException: Недостаточно привилегий для завершения операции. ---> System.Data.Services.Client.DataServiceQueryException: при обработке этого запроса произошла ошибка. ---> System.Data.Services.Client.DataServiceClientException: {"odata.error": {"code": "Authorization_RequestDenied", "message": {"lang": "en", "value": "Недостаточно привилегий для завершения операции.}}}

Похоже, что, несмотря на предоставление правильных разрешений, правильный ресурс и возможность получить токен, все еще что-то не хватает.

+0

Вы нашли способ решить исключение вы получили? Потому что я тоже получаю это точное исключение ** Authorization_RequestDenied ** –

+0

@Arunkumar Да. См. Ответ, который я добавил 21 января. Проконсультируйтесь с вашими администраторами арендаторов для AAD. – VJK

ответ

0

Оказывается, реальная проблема связана не с кодом. Я не администратор AAD. Похоже, что любое приложение, требующее выполнить аутентификацию против AAD у нашего арендатора, должно иметь разрешения, разрешенные администраторами AAD. После того, как они включили разрешения для моего приложения (и также приняли участие в регистрации AAD), это начало работать.

1

Ключевое значение, которое следует учитывать, заключается в том, что ваше приложение будет безгласным клиентом, запускаемым с безопасного сервера или настольного клиента, запускаемого пользователями на своих компьютерах.

Если первое, то ваша заявка считается конфиденциальным клиентом и может быть доверена секретами, то есть ключами. Если это ваш сценарий, который является сценарием, охватываемым образцом, то вам нужно использовать clientId и clientSecret.

Наиболее вероятной причиной вы не видя Ключи раздел Настройка странице вашего приложения является то, что вместо выбора веб-приложения и/или Web API в соответствии с шагом # 7 в образце, вы выбрано Собственное клиентское приложение при первом создании приложения. Этот «тип» не может быть изменен, поэтому вам нужно создать новое приложение.

Если ваш сценарий является последним, ваша заявка считается публичным клиентом и не может быть доверена секретами, и в этом случае вашими опциями являются приглашение пользователя для учетных данных. В противном случае, даже если ваше приложение имеет собственный уровень авторизации, его можно легко декомпилировать, а секрет извлечь и использовать.

Ваш URL-адрес ресурса, кстати, правильный.

+0

Спасибо @ Саке.Я заново создал приложение как родное приложение. Также предоставлены разрешения приложений вместо делегированных разрешений для чтения данных каталога. Кроме того, похоже, что URI ресурса не должен включать идентификатор арендатора. После этих исправлений я могу получить токен. Однако, пытаясь получить доступ к данным каталога, я все равно получаю отказ в запросе. {"odata.error": {"code": "Authorization_RequestDenied", "message": {"lang": "en", "value": "Недостаточно привилегий для завершения операции."}}} См. EDITS в оригинальном вопросе для обновленного кода. – VJK