401- 使用 REST API Dynamics CRM with Azure AD 进行未经授权的身份验证

401- Unauthorized authentication using REST API Dynamics CRM with Azure AD

我正在尝试使用 Azure AD oAuth 2 身份验证访问 Dynamics CRM Online REST API。为此,我遵循了以下步骤:

- 我已经在 Azure
中注册了一个 Web 应用程序 and/or web api - 将 Dynamics CRM 的权限配置为具有委派权限 "Access CRM Online as organization user"
- 并创建了一个有效期为 1 年的密钥,并保留生成的客户端 ID。

在 Azure 上配置 Web 应用程序后,我在 .NET/C# 中创建了一个控制台应用程序,它使用 ADAL 发出一个简单的请求,在本例中是检索帐户列表:

    class Program
{
    private static string ApiBaseUrl = "https://xxxxx.api.crm4.dynamics.com/";
    private static string ApiUrl = "https://xxxxx.api.crm4.dynamics.com/api/data/v8.1/";
    private static string ClientId = "2a5dcdaf-2036-4391-a3e5-9d0852ffe3f2";
    private static string AppKey = "symCaAYpYqhiMK2Gh+E1LUlfxbMy5X1sJ0/ugzM+ur0=";

    static void Main(string[] args)
    {
        AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(ApiUrl)).Result;

        var clientCredential = new ClientCredential(ClientId, AppKey);

        var authenticationContext = new AuthenticationContext(ap.Authority);
        var authenticationResult = authenticationContext.AcquireToken(ApiBaseUrl, clientCredential);

        var httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);

        var result = httpClient.GetAsync(Path.Combine(ApiUrl, "accounts")).Result;         
    }
}

我成功检索了访问令牌,但是当我尝试对 CRM 执行 http 请求时,我总是收到 401 - 未授权状态代码。我错过了什么?

你的 ClientId,来自 Azure 的 AppKey,所以 ap.Authorityvar authenticationContext = new AuthenticationContext(ap.Authority);

中应该是 https://login.microsoftonline.com/tenantid

我认为您至少无法绕过向某种 "integration account" 提供用户凭据。您可以通过以下方式避免更传统的 popup/redirect OAUTH 流程:

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.IO;
using System.Net;

namespace ConsoleApplication2
{
    class Program
    {
        private static string API_BASE_URL = "https://<CRM DOMAIN>/";
        private static string API_URL = "https://<CRM DOMAIN>/api/data/v8.1/";
        private static string CLIENT_ID = "<CLIENT ID>";

        static void Main(string[] args)
        {
            var userCredential = new UserCredential("<USERNAME>", "<PASSWORD>");
            var authContext = new AuthenticationContext("https://login.windows.net/common", false);
            var result = authContext.AcquireToken(API_BASE_URL, CLIENT_ID, userCredential);

            var httpClient = HttpWebRequest.CreateHttp(Path.Combine(API_URL, "accounts"));
            httpClient.Headers.Add(HttpRequestHeader.Authorization, "Bearer:" + result.AccessToken);
            using (var sr = new StreamReader(httpClient.GetResponse().GetResponseStream()))
            {
                Console.WriteLine(sr.ReadToEnd());
            }

            Console.ReadLine();
        }
    }
}

注意:我使用的是旧版本的 ADAL (2.19.208020213),因为 password 参数似乎已从 UserCredential 构造函数中取出。

编辑: CRM 现在支持 Server to Server Authentication,允许您创建应用程序用户。

我建议您看一下 Server-to-Server (S2S) 身份验证,它已添加到最新版本的 Dynamics 365 中。

通过使用 S2S,您不需要付费的 Dynamics 365 许可证。应用程序根据存储在 Dynamics 365 应用程序用户记录中的 Azure AD 对象 ID 值标识的服务主体而不是用户凭据进行身份验证。

可在此处找到更多信息: https://msdn.microsoft.com/en-us/library/mt790168.aspx https://msdn.microsoft.com/en-us/library/mt790170.aspx

1 年零 2 个月后,同样的代码可以完美运行。正如许多人所说,Dynamics 365 同时开始支持服务器到服务器 (S2S) 身份验证。我当时必须做的唯一一步是创建一个应用程序用户。 有关如何进行此身份验证的更多信息,请查看此网站:https://msdn.microsoft.com/en-us/library/mt790170.aspx

您可能需要在 CRM 中设置应用程序用户以匹配您的 Azure 应用程序: https://msdn.microsoft.com/en-us/library/mt790170.aspx

虽然您可以在 C# 中设置不记名令牌,但由于 CRM 级别的权限,对 CRM 资源的 Web 请求可能会失败。

感谢大家的回答。我终于设法使用 ADAL 3.

访问 Dynamics CRM OData API

由于很多人在执行此操作时仍然遇到问题,请参阅以下步骤:

应用注册

  1. 使用 Dynamics CRM 订阅的 Office 365 管理员用户登录 portal.azure.com

  2. 转到 Azure 活动 Director\App 注册并添加新应用程序注册

  3. 输入"Name"和"Sign-on URL",URL可以是任何东西(例如https://localhost

  4. Select刚刚创建的注册应用,进入Settings\Keys

  5. 输入密钥描述,单击“保存”并复制值(并保留它,因为稍后需要它)。同时复制已注册应用程序的应用程序 ID。

  6. 转到"Required Permissions",单击添加,select "Dynamics CRM Online"然后勾选"Access CRM Online as organisation users"。

这些步骤使客户端应用程序能够使用您在步骤 5 中创建的应用程序 ID 和客户端密码访问 Dynamics CRM。 您的客户端应用程序现在可以针对 Azure AD 进行身份验证,并获得访问 CRM Online 的权限。但是,CRM Online 不知道 "client application" 或 "user"。如果您尝试访问,CRM API 将响应 401。

添加 CRM 应用程序用户

要让 CRM 了解 "client application" 或 "user",您需要添加应用程序用户。

  1. 转到 CRM\Security 角色,创建一个新的安全角色或只复制 "System Administrator" 角色

  2. 转到CRM\Settings\Security\Users,创建一个新用户,将表单更改为"Application User"

  3. 使用您在上一步中获得的应用程序 ID 输入必填字段。保存后,CRM 将自动填充 Azure AD 对象 ID 和 URI。

  4. 将用户添加到从上一步创建的安全角色。

现在您应该可以使用 HttpClient 和 ADAL 使用下面的示例代码访问 CRM API:

var ap = await AuthenticationParameters.CreateFromResourceUrlAsync(
                new Uri("https://*****.api.crm6.dynamics.com/api/data/v9.0/"));

String authorityUrl = ap.Authority;
String resourceUrl = ap.Resource;

var authContext = new AuthenticationContext(authorityUrl);
var clientCred = new ClientCredential("Application ID", "Client Secret");
var test = await authContext.AcquireTokenAsync(resourceUrl, clientCred);

Console.WriteLine(test.AccessToken);

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", test.AccessToken);

    var response = await client.GetAsync("https://*****.api.crm6.dynamics.com/api/data/v9.0/contacts");
    var contacts = await response.Content.ReadAsStringAsync();

    Console.WriteLine(contacts);
}