如何使用非交互式用户对CRM Online进行身份验证?

时间:2016-03-11 19:13:28

标签: dynamics-crm-online

我正在创建一个需要访问CRM Online 2016中数据的控制台应用程序。这将作为预定作业运行,而不是以交互方式运行。我似乎需要使用OAuth进行身份验证。

我已经完成了以下工作:

  • 我在CRM中创建了一个非交互式用户,用于此集成。 - 我已经在Azure AD中注册了我的应用程序并拥有客户端ID。

我无法弄清楚如何对Web服务进行身份验证。我被引导到这篇MSDN文章:

https://msdn.microsoft.com/en-us/library/gg327838.aspx

它显示了如何进行身份验证,但它显示的示例会弹出一个窗口,要求用户键入用户/密码。这对我不起作用,因为此应用程序不会以交互方式运行。我到处寻找,但是没有找到任何文档,告诉我如何在没有弹出窗口的情况下进行身份验证。

似乎我应该能够使用AuthenticationContext.AcquireTokenByAuthorizationCode,但我找不到任何关于如何使用它的好例子。

非常感谢任何方向!

2 个答案:

答案 0 :(得分:1)

  • 将NuGet引用添加到Microsoft.CrmSdk.XrmTooling.CoreAssembly。
  • 在您的应用配置中包含连接字符串(也可以包含用户名和密码)
<connectionStrings>
  <add name="CrmService" connectionString="Url=https://UniqueOrgName.crm.dynamics.com;AuthType=Office365;"/>
</connectionStrings>

请拨打此代码:

private static CrmServiceClient CreateCrmConnection(string userName, string password)
{
    var url = ConfigurationManager.ConnectionStrings["CrmService"].ConnectionString;
    var client = new CrmServiceClient(string.Format("{0}UserName={1};Password={2};", url, userName, password));

    if (client.IsReady)
    {
        return client;
    }
    else
    {
        // Display the last error.
        Console.WriteLine("Error occurred: {0}", client.LastCrmError);

        // Display the last exception message if any.
        Console.WriteLine(client.LastCrmException.Message);
        Console.WriteLine(client.LastCrmException.Source);
        Console.WriteLine(client.LastCrmException.StackTrace);

        throw new Exception("Unable to Connect to CRM");
    }
}

答案 1 :(得分:0)

如果您使用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());
    }
}

如果遇到访问被拒绝的问题,另请参阅https://stackoverflow.com/a/54775571/185200,并验证您是否已正确配置/验证了应用程序。