Недавно я сделал нечто подобное, но не полагаясь на функцию аутентификации подписки Azure для подключения к D365. В моем случае вызовы к функциям Azure приходили из других мест, но обратное соединение не изменилось. Аутентификация НЕ проходит ни в одном из этих случаев. Если пользователь AAD аутентифицируется в вашем приложении-функции, вам все равно необходимо подключиться к D365 с помощью пользователя приложения, а затем выдать себя за пользователя, который вам позвонил.
Во-первых, убедитесь, что приложение, которое вы зарегистрировали в Azure AD в разделе «Регистрация приложений», относится к типу «Веб-приложение / API», а не «Собственное». Измените настройки зарегистрированного приложения и убедитесь в следующем:
- Не принимайте во внимание идентификатор приложения, который я позже буду называть appId.
- В разделе «Доступ к API - необходимые разрешения» добавьте Dynamics CRM Online (Microsoft.CRM), а НЕ Dynamics 365.
- В разделе «Доступ к API - Ключи» создайте ключ с соответствующим сроком действия. Вы можете создать несколько ключей, если у вас есть несколько функций / приложений, которые подключаются обратно как это «Приложение». Позже я буду называть этот ключ clientSecret.
Если параметр «Ключи» недоступен, вы зарегистрировали собственное приложение.
Я сохранил appId и clientSecret в разделе конфигурации приложения приложения-функции и получил к ним доступ, используя обычную коллекцию System.Configuration.ConfigurationManager.AppSettings.
В приведенных ниже примерах используется вызов AuthenticationParameters для поиска URL-адресов органов власти и ресурсов, но вы также можете легко создать эти URL-адреса вручную, используя бесчисленные примеры в Интернете. Я считаю, что это просто обновится, если они когда-либо изменятся, так что меньше работы позже.
Это простые примеры, и я замалчиваю необходимость обновлять токены и все такое.
Затем для доступа к D365 с помощью OData:
string odataUrl = "https://org.crm6.dynamics.com/api/data/v8.2/"; // trailing slash actually matters
string appId = "some-guid";
string clientSecret = "some key";
AuthenticationParameters authArg = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(odataUrl)).Result;
AuthenticationContext authCtx = new AuthenticationContext(authArg.Authority);
AuthenticationResult authRes = authCtx.AcquireTokenAsync(authArg.Resource, new ClientCredential(appId, clientSecret)).Result;
using (HttpClient client = new HttpClient()) {
client.TimeOut = TimeSpan.FromMinutes (2);
client.DefaultRequestHeaders.Add("Authorization", authRes.CreateAuthorizationHeader ());
using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, $"{odataUrl}accounts?$select=name&$top=10")) {
using (HttpResponseMessage res = client.SendAsync(req).Result) {
if (res.IsSuccessStatusCode) {
Console.WriteLine(res.Content.ReadAsStringAsync().Result);
}
else {
// cry
}
}
}
}
Если вы хотите получить доступ к D365 с помощью службы организации и LINQ, используйте следующее. Две основные части, на которые мне потребовалось некоторое время, - это формат этого странно выглядящего URL-адреса organization.svc и использование Microsoft.Xrm.Sdk.WebServiceClient.OrganizationWebProxyClient вместо Tooling:
string odataUrl = "https://org.crm6.dynamics.com/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2"; // don't question the url, just accept it.
string appId = "some-guid";
string clientSecret = "some key";
AuthenticationParameters authArg = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(odataUrl)).Result;
AuthenticationContext authCtx = new AuthenticationContext(authArg.Authority);
AuthenticationResult authRes = authCtx.AcquireTokenAsync(authArg.Resource, new ClientCredential(appId, clientSecret)).Result;
using (OrganizationWebProxyClient webProxyClient = new OrganizationWebProxyClient(new Uri(orgSvcUrl), false)) {
webProxyClient.HeaderToken = authRes.AccessToken;
using (OrganizationServiceContext ctx = new OrganizationServiceContext((IOrganizationService)webProxyClient)) {
var accounts = (from i in ctx.CreateQuery("account") orderby i["name"] select i).Take(10);
foreach (var account in accounts)
Console.WriteLine(account["name"]);
}
}
Не уверен, в каком контексте вы вернетесь при регистрации Webhook, еще не пробовал, но просто убедился, что токен-носитель в заголовке авторизации обычно делает это, и два приведенных выше примера вводят его по-разному, чтобы вы могли соедините вместе то, что нужно отсюда.
person
Alexander Liffers
schedule
11.05.2018