![]() |
#2 |
Administrator
|
D365FO: Аутенфикация при использовании веб-сервиса
Независимо от применяемой технологии SOAP / JSON отдельной задачей стоит аутенфикация внешнего приложения при подключении к D365FO.
Для локальной (On premise) версии аутенфикация осуществляется через логин / пароль, которые проверяются службой ADFS (Active Directory Federation Services) Для облачной (Cloud) версии аутенфикация осуществляется через токен, т.е. большую текстовую строку, которая возвращается в приложение службой аутенфикации. Токен вычисляется на основе 4-х параметров:
Образец кода для аутенфикации лежит в https://github.com/microsoft/Dynamic...OAuthHelper.cs в методе GetAuthenticationHeader. X++: using Microsoft.IdentityModel.Clients.ActiveDirectory; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AuthenticationUtility { public class OAuthHelper { /// <summary> /// The header to use for OAuth authentication. /// </summary> public const string OAuthHeader = "Authorization"; /// <summary> /// Retrieves an authentication header from the service. /// </summary> /// <returns>The authentication header for the Web API call.</returns> public static string GetAuthenticationHeader(bool useWebAppAuthentication = false) { string aadTenant = ClientConfiguration.Default.ActiveDirectoryTenant; string aadClientAppId = ClientConfiguration.Default.ActiveDirectoryClientAppId; string aadClientAppSecret = ClientConfiguration.Default.ActiveDirectoryClientAppSecret; string aadResource = ClientConfiguration.Default.ActiveDirectoryResource; AuthenticationContext authenticationContext = new AuthenticationContext(aadTenant, false); AuthenticationResult authenticationResult; if (useWebAppAuthentication) { if (string.IsNullOrEmpty(aadClientAppSecret)) { Console.WriteLine("Please fill AAD application secret in ClientConfiguration if you choose authentication by the application."); throw new Exception("Failed OAuth by empty application secret."); } try { // OAuth through application by application id and application secret. var creadential = new ClientCredential(aadClientAppId, aadClientAppSecret); authenticationResult = authenticationContext.AcquireTokenAsync(aadResource, creadential).Result; } catch (Exception ex) { Console.WriteLine(string.Format("Failed to authenticate with AAD by application with exception {0} and the stack trace {1}", ex.ToString(), ex.StackTrace)); throw new Exception("Failed to authenticate with AAD by application."); } } else { // OAuth through username and password. string username = ClientConfiguration.Default.UserName; string password = ClientConfiguration.Default.Password; if (string.IsNullOrEmpty(password)) { Console.WriteLine("Please fill user password in ClientConfiguration if you choose authentication by the credential."); throw new Exception("Failed OAuth by empty password."); } try { // Get token object var userCredential = new UserPasswordCredential(username, password); ; authenticationResult = authenticationContext.AcquireTokenAsync(aadResource, aadClientAppId, userCredential).Result; } catch (Exception ex) { Console.WriteLine(string.Format("Failed to authenticate with AAD by the credential with exception {0} and the stack trace {1}", ex.ToString(), ex.StackTrace)); throw new Exception("Failed to authenticate with AAD by the credential."); } } // Create and get JWT token return authenticationResult.CreateAuthorizationHeader(); } } } X++: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AuthenticationUtility { public partial class ClientConfiguration { public static ClientConfiguration Default { get { return ClientConfiguration.OneBox; } } public static ClientConfiguration OneBox = new ClientConfiguration() { // You only need to populate this section if you are logging on via a native app. For Service to Service scenarios in which you e.g. use a service principal you don't need that. UriString = "https://usnconeboxax1aos.cloud.onebox.dynamics.com/", UserName = "tusr1@TAEOfficial.ccsctp.net", // Insert the correct password here for the actual test. Password = "", // You need this only if you logon via service principal using a client secret. See: [url]https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/data-entities/services-home-page[/url] to get more data on how to populate those fields. // You can find that under AAD in the azure portal ActiveDirectoryResource = "https://usnconeboxax1aos.cloud.onebox.dynamics.com", // Don't have a trailing "/". Note: Some of the sample code handles that issue. ActiveDirectoryTenant = "https://login.windows-ppe.net/TAEOfficial.ccsctp.net", // Some samples: [url]https://login.windows.net/yourtenant.onmicrosoft.com[/url], [url]https://login.windows.net/microsoft.com[/url] ActiveDirectoryClientAppId = "d8a9a121-b463-41f6-a86c-041272bdb340", // Insert here the application secret when authenticate with AAD by the application ActiveDirectoryClientAppSecret = "", // Change TLS version of HTTP request from the client here // Ex: TLSVersion = "1.2" // Leave it empty if want to use the default version TLSVersion = "", }; public string TLSVersion { get; set; } public string UriString { get; set; } public string UserName { get; set; } public string Password { get; set; } public string ActiveDirectoryResource { get; set; } public String ActiveDirectoryTenant { get; set; } public String ActiveDirectoryClientAppId { get; set; } public string ActiveDirectoryClientAppSecret { get; set; } } } Я изначально предполагаю, что имеется виртуалка OneBox, пользователь Admin которой сопоставлен с какой-нибудь учетной записью типа vasya@ivan-petrov.ru и есть возможность (в т.ч. права) под какой-нибудь учетной записью из домена @ivan-petrov.ru сделать настройки в Azure Active Directory. Итак, заходим на https://portal.azure.com/ и выбираем ярлык Azure Active Directory Слева выбираем пункт Регистрация приложений, жмем кнопку Новая регистрация и указываем имя приложения. Впоследствии мы свяжем данное приложение с пользователем, под которым внешнее приложение будет подключаться к нашему экземпляру системы D365FO, поэтому я указываю в качестве названия приложения - название нашего веб-сервиса Больше ничего указывать не обязательно, поэтому можно нажать на кнопку Зарегистрировать. После этого у нас откроется страничка, где уже будет нашему приложению присвоен Идентификатор приложения, он же Application Id (AppId), который мы впоследствии укажем в "четверке" параметров подключения в поле AppId Далее этому приложению нужно добавить секретный идентификатор, тот - который у нас будет указан в поле AppSecretId. Для этого, не уходя со странички приложения выбираем слева пункт "Сертификаты и секреты" И нажимаем кнопку "Новый секрет клиента" Указываем описание (любое) и срок действия - 1, 2 года или бессрочно и жмем кнопку Добавить Мы получаем секретный идентификатор, который впоследствии и нужно будет подставить в поле AppSecret. Его желательно сразу сохранить, т.к. потом на этой странице он уже отображаться не будет и его придется заново генерировать (в то время, как идентификатор приложения можно будет увидеть при повторном открытии страницы). Теперь нам нужно ассоциировать наше приложение с пользователем в D365FO. Для этого нужно зайти в систему в модуль Администрирование и выбрать пункт меню Настройка - Приложения Azure Active Directory И настроить соответствие между идентификатором приложения (AppId, код клиента) и пользователем системы (пользователь может и должен быть ограничен в правах) Дело осталось за малым - подготовить проект на C#, используя заготовки Microsoft и полученные идентификаторы AppId и AppSecret. На всякий случай отмечу, что в данном примере у меня получились следующие значения: Цитата:
AppId: "d4a93f6d-1d46-4e33-a258-3aa3ae7cb819"
AppSecretId: "J6Z86h8.JhXxYH.43TM5Bap7~_UZ29wI_R" Tenant: "ivan-petrov.ru" Resource: "https://usnconeboxax1aos.cloud.onebox.dynamics.com" X++: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AuthenticationUtility { public partial class ClientConfiguration { public static ClientConfiguration Default { get { return ClientConfiguration.OneBox; } } public static ClientConfiguration OneBox = new ClientConfiguration() { // You only need to populate this section if you are logging on via a native app. For Service to Service scenarios in which you e.g. use a service principal you don't need that. UriString = "", UserName = "", // Insert the correct password here for the actual test. Password = "", // You need this only if you logon via service principal using a client secret. See: [url]https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/data-entities/services-home-page[/url] to get more data on how to populate those fields. // You can find that under AAD in the azure portal ActiveDirectoryResource = "https://usnconeboxax1aos.cloud.onebox.dynamics.com", // Don't have a trailing "/". Note: Some of the sample code handles that issue. ActiveDirectoryTenant = "https://login.windows.net/ivan-petrov.ru", // Some samples: [url]https://login.windows.net/yourtenant.onmicrosoft.com[/url], [url]https://login.windows.net/microsoft.com[/url] ActiveDirectoryClientAppId = "d4a93f6d-1d46-4e33-a258-3aa3ae7cb819", // Insert here the application secret when authenticate with AAD by the application ActiveDirectoryClientAppSecret = "J6Z86h8.JhXxYH.43TM5Bap7~_UZ29wI_R", // Change TLS version of HTTP request from the client here // Ex: TLSVersion = "1.2" // Leave it empty if want to use the default version TLSVersion = "", }; public string TLSVersion { get; set; } public string UriString { get; set; } public string UserName { get; set; } public string Password { get; set; } public string ActiveDirectoryResource { get; set; } public String ActiveDirectoryTenant { get; set; } public String ActiveDirectoryClientAppId { get; set; } public string ActiveDirectoryClientAppSecret { get; set; } } } - Отсутствием значений переменных UserName, Password и UriString - Заполненными значениями переменных ActiveDirectoryResource (URL нашей системы D365FO), ActiveDirectoryTenant (строка "https://login.windows.net/", к которой добавлен наш домен ivan-petrov.ru), ActiveDirectoryClientAppId и ActiveDirectoryClientAppSecret, полученных при регистрации приложения в Azure AD
__________________
Возможно сделать все. Вопрос времени Последний раз редактировалось sukhanchik; 08.07.2020 в 00:03. |
|
|
|