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.Authority
在 var 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
由于很多人在执行此操作时仍然遇到问题,请参阅以下步骤:
应用注册
使用 Dynamics CRM 订阅的 Office 365 管理员用户登录 portal.azure.com
。
转到 Azure 活动 Director\App 注册并添加新应用程序注册
输入"Name"和"Sign-on URL",URL可以是任何东西(例如https://localhost)
Select刚刚创建的注册应用,进入Settings\Keys
输入密钥描述,单击“保存”并复制值(并保留它,因为稍后需要它)。同时复制已注册应用程序的应用程序 ID。
转到"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",您需要添加应用程序用户。
转到 CRM\Security 角色,创建一个新的安全角色或只复制 "System Administrator" 角色
转到CRM\Settings\Security\Users,创建一个新用户,将表单更改为"Application User"
使用您在上一步中获得的应用程序 ID 输入必填字段。保存后,CRM 将自动填充 Azure AD 对象 ID 和 URI。
将用户添加到从上一步创建的安全角色。
现在您应该可以使用 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);
}
我正在尝试使用 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.Authority
在 var 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由于很多人在执行此操作时仍然遇到问题,请参阅以下步骤:
应用注册
使用 Dynamics CRM 订阅的 Office 365 管理员用户登录
portal.azure.com
。转到 Azure 活动 Director\App 注册并添加新应用程序注册
输入"Name"和"Sign-on URL",URL可以是任何东西(例如https://localhost)
Select刚刚创建的注册应用,进入Settings\Keys
输入密钥描述,单击“保存”并复制值(并保留它,因为稍后需要它)。同时复制已注册应用程序的应用程序 ID。
转到"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",您需要添加应用程序用户。
转到 CRM\Security 角色,创建一个新的安全角色或只复制 "System Administrator" 角色
转到CRM\Settings\Security\Users,创建一个新用户,将表单更改为"Application User"
使用您在上一步中获得的应用程序 ID 输入必填字段。保存后,CRM 将自动填充 Azure AD 对象 ID 和 URI。
将用户添加到从上一步创建的安全角色。
现在您应该可以使用 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);
}