Как подключить серверную службу к Dynamics Online

Я изменяю внутреннее приложение управления для подключения к нашему онлайн-экземпляру Dynamics 2016.

После некоторых онлайн-уроков, я использовал OrganizationServiceProxy снаружи Microsoft.Xrm.Sdk.Client из SDK.

Похоже, что для подключения требуются имя пользователя и пароль, что прекрасно работает, но я бы хотел подключиться таким образом, чтобы не требовались данные учетной записи конкретного пользователя. Я не думаю, что примеры OAuth, которые я видел, являются подходящими, поскольку нет пользовательского интерфейса, и нет реального человека, который бы показывал запрос OAuth.

public class DynamicsHelper
{
    private OrganizationServiceProxy service;

    public void Connect(string serviceUri, string username, string password)
    {
            var credentials = new ClientCredentials();
            credentials.UserName.UserName = username;
            credentials.UserName.Password = password;

            var organizationUri = new Uri(serviceUri);
            this.service = new OrganizationServiceProxy(organizationUri, null, credentials, null);
    }
}

Есть ли способ подключения с помощью токена приложения или ключа API?

1 ответ

Я обнаружил, что, чтобы сделать это успешно, вам нужно настроить все следующее:

  1. Создайте регистрацию приложения в Azure AD:
    • предоставить ему разрешения API для Dynamics, в частности "Access Dynamics 365 как пользователи организации"
    • дать ему фиктивный веб-редирект URI, такой как http://localhost/auth
    • создать секрет клиента и сохранить его на потом
  2. Создайте учетную запись пользователя в Azure AD и предоставьте ей разрешения для Dynamics.
  3. Создайте запись пользователя приложения в Dynamics с тем же адресом электронной почты, что и у неинтерактивной учетной записи выше.
  4. Аутентифицируйте ваше приложение, используя созданную вами учетную запись.

На шаге 4 вы захотите открыть новое окно инкогнито, создайте URL-адрес, используя следующий шаблон, и войдите в систему, используя учетные данные своей учетной записи на шаге 2:

https://login.microsoftonline.com/<your aad tenant id>/oauth2/authorize?client_id=<client id>&response_type=code&redirect_uri=<redirect uri from step 1>&response_mode=query&resource=https://<organization name>.<region>.dynamics.com&state=<random value>

Когда это будет сделано, вы должны увидеть, что у пользователя приложения Dynamics есть идентификатор приложения и идентификатор URI приложения.

Теперь, используя ClientId и ClientSecret, а также некоторые другие переменные, характерные для организации, вы можете пройти проверку подлинности с помощью Azure Active Directory (AAD), чтобы получить токен oauth и создать OrganizationWebProxyClient, Я никогда не нашел полного примера кода для этого, но я разработал следующее для своих собственных целей. Обратите внимание, что срок действия приобретаемого токена составляет 1 час.

internal class ExampleClientProvider
{
    // Relevant nuget packages:
    // <package id="Microsoft.CrmSdk.CoreAssemblies" version="9.0.2.9" targetFramework="net472" />
    // <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="4.5.1" targetFramework="net461" />

    // Relevant imports:
    // using Microsoft.IdentityModel.Clients.ActiveDirectory;
    // using Microsoft.Crm.Sdk.Messages;
    // using Microsoft.Xrm.Sdk;
    // using Microsoft.Xrm.Sdk.Client;
    // using Microsoft.Xrm.Sdk.WebServiceClient;

    private const string TenantId = "<your aad tenant id>";                 // from your app registration overview "Directory (tenant) ID"
    private const string ClientId = "<your client id>";                     // from your app registration overview "Application (client) ID"
    private const string ClientSecret = "<your client secret>";             // secret generated in step 1
    private const string LoginUrl = "https://login.microsoftonline.com";    // aad login url
    private const string OrganizationName = "<your organization name>";     // check your dynamics login url, e.g. https://<organization>.<region>.dynamics.com
    private const string OrganizationRegion = "<your organization region>"; // might be crm for north america, check your dynamics login url    

    private string GetServiceUrl()
    {
        return $"{GetResourceUrl()}/XRMServices/2011/Organization.svc/web";
    }

    private string GetResourceUrl()
    {
        return $"https://{OrganizationName}.api.{OrganizationRegion}.dynamics.com";
    }

    private string GetAuthorityUrl()
    {
        return $"{LoginUrl}/{TenantId}";
    }

    public async Task<OrganizationWebProxyClient> CreateClient()
    {
        var context = new AuthenticationContext(GetAuthorityUrl(), false);
        var token = await context.AcquireTokenAsync(GetResourceUrl(), new ClientCredential(ClientId, ClientSecret));

        return new OrganizationWebProxyClient(new Uri(GetServiceUrl()), true)
        {
            HeaderToken = token.AccessToken,
            SdkClientVersion = "9.1"
        };
    }

    public async Task<OrganizationServiceContext> CreateContext()
    {
        var client = await CreateClient();
        return new OrganizationServiceContext(client);
    }

    public async Task TestApiCall()
    {
        var context = await CreateContext();

        // send a test request to verify authentication is working
        var response = (WhoAmIResponse) context.Execute(new WhoAmIRequest());
    }
}

Если я правильно понимаю ваш вопрос, вы хотите подключиться к Dynamics 2016 (Dynamics 365) через Зарегистрированное приложение Azure с ClientId и Secret вместо имени пользователя и пароля. Если это правильно, да, это возможно с OrganizationWebProxyClient. Вы даже можете использовать строго типы сборок.

var organizationWebProxyClient = new OrganizationWebProxyClient(GetServiceUrl(), true);
organizationWebProxyClient.HeaderToken = authToken.AccessToken;

OrganizationRequest request = new OrganizationRequest()
{
    RequestName = "WhoAmI"
};

WhoAmIResponse response = organizationWebProxyClient.Execute(new WhoAmIRequest()) as WhoAmIResponse;
Console.WriteLine(response.UserId);

Contact contact = new Contact();
contact.EMailAddress1 = "jennie.whiten@mycompany.com";
contact.FirstName = "Jennie";
contact.LastName = "White";
contact.Id = Guid.NewGuid();

organizationWebProxyClient.Create(contact);

Чтобы получить AccessToken, обратитесь к следующему сообщению Подключение к Dynamics CRM WebApi из консольного приложения.

Заменить строку 66 (полный исходный код)

authToken = await authContext.AcquireTokenAsync(resourceUrl, clientId, new Uri(redirectUrl), new PlatformParameters(PromptBehavior.Never));

с

authToken = await authContext.AcquireTokenAsync( resourceUrl, new ClientCredential(clientId, secret));

Можно также проверить следующее приложение Link Authenticate Azure Function App для подключения к Dynamics 365 CRM в Интернете, в котором описано, как защитить свои учетные данные с помощью хранилища ключей Azure.

С помощью Microsoft Dynamics CRM Online или развертываний в Интернете. При использовании веб-API для CRM Online или локального развертывания в Интернете (IFD) необходимо использовать OAuth, как описано в разделе Подключение к веб-службам Microsoft Dynamics CRM с помощью OAuth.

Прежде чем вы сможете использовать проверку подлинности OAuth для подключения к веб-службам CRM, ваше приложение должно быть сначала зарегистрировано в Microsoft Azure Active Directory. Azure Active Directory используется для проверки того, что вашему приложению разрешен доступ к бизнес-данным, хранящимся в клиенте CRM.

 // TODO Substitute your correct CRM root service address, 
 string resource = "https://mydomain.crm.dynamics.com";

// TODO Substitute your app registration values that can be obtained after you
// register the app in Active Directory on the Microsoft Azure portal.
string clientId = "e5cf0024-a66a-4f16-85ce-99ba97a24bb2";
string redirectUrl = "http://localhost/SdkSample";


// Authenticate the registered application with Azure Active Directory.
AuthenticationContext authContext = 
    new AuthenticationContext("https://login.windows.net/common", false);
AuthenticationResult result = 
    authContext.AcquireToken(resource, clientId, new Uri(redirectUrl));

PS: Что касается вашего метода, то лучше не хранить пароль в виде открытого текста, не шифровать его и не шифровать разделы конфигурации для максимальной безопасности.

Смотрите прохождение здесь

Надеюсь это поможет:)

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