首页 文章

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

提问于
浏览
12

我正在尝试使用Azure AD oAuth 2身份验证访问Dynamics CRM Online REST API . 为此,我按照以下步骤操作:

  • 我在Azure中注册了一个Web应用程序和/或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进行httprequest时,我总是得到一个 401 - Unauthorized status code . 我错过了什么?

6 回答

  • 0

    谢谢大家的回答 . 我终于使用ADAL 3访问了Dynamics CRM OData API .

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

    应用注册

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

    • 转到Azure Active Director \ App注册并添加新的应用程序注册

    • 输入"Name"和"Sign-on URL",URL可以是任何内容(例如https://localhost

    • 选择刚刚创建的注册应用程序,转到设置\键

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

    • 转到“必需权限”,单击“添加”,选择“Dynamics CRM Online”,然后选中“以组织用户身份访问CRM Online” .

    这些步骤使客户端应用程序能够使用您在步骤5中创建的应用程序ID和客户端密钥来访问Dynamics CRM . 您的客户端应用程序现在能够针对Azure AD获得访问CRM Online的权限 . 但是,CRM Online不知道这个"client application"或"user" . 如果您尝试访问它,CRM API将响应401 .

    添加CRM应用程序用户

    要让CRM了解“客户端应用程序”或“用户”,您需要添加应用程序用户 .

    • 转到CRM \安全角色,创建新的安全角色或只复制“系统管理员”角色

    • 转到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);
    }
    
  • 4

    我建议您查看服务器到服务器(S2S)身份验证,该身份验证已在最新版本中添加到Dynamics 365中 .

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

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

  • 0

    1年零2个月后, this same code works perfectly . 正如许多人所说,Dynamics 365在此期间开始支持服务器到服务器(S2S)身份验证 . 我不得不做的唯一一步就是创建一个应用程序用户 . 有关如何进行此身份验证的详细信息,请访问以下网站:https://msdn.microsoft.com/en-us/library/mt790170.aspx

  • 3

    你的ClientId,来自Azure的AppKey,所以 ap.Authority 应该是 https://login.microsoftonline.com/tenantid in var authenticationContext = new AuthenticationContext(ap.Authority);

  • 0

    我不认为你能够至少为某种“集成帐户”提供用户凭据 . 您可以使用以下内容避免更传统的弹出/重定向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 构造函数中删除 .

    EDIT: CRM现在支持Server to Server Authentication,它允许您创建应用程序用户 .

  • 3

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

    虽然您可以在C#中设置Bearer Token,但由于CRM级别权限,对CRM资源的Web请求可能会失败 .

相关问题