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

     2023-03-04     272

关键词:

【中文标题】401- 使用 REST API Dynamics CRM 和 Azure AD 进行未经授权的身份验证【英文标题】:401- Unauthorized authentication using REST API Dynamics CRM with Azure AD 【发布时间】:2016-09-09 23:44:52 【问题描述】:

我正在尝试使用 Azure AD oAuth 2 身份验证访问 Dynamics CRM Online REST API。为此,我遵循了以下步骤: - 我在 Azure 中注册了一个 Web 应用程序和/或 Web API - 将 Dynamics CRM 的权限配置为具有“以组织用户身份访问 CRM Online”的委派权限 - 并创建了一个有效期为 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 - 未授权状态代码。我错过了什么?

【问题讨论】:

我相信它对令牌的权限不正确。您正在做的是使用应用程序凭据来获取包含。您在添加 CRM 时选择的权限是 Delegated PErmissions。两者都是不同的东西。如果使用同一目录下用户的 User Creds 进行身份验证和访问会怎样? 我之前创建了一个本地客户端应用程序,并成功地与 CRM 集成,但我必须提供用户凭据才能从 Azure 获取令牌。我的目标是完全避免使用用户凭据。为此,我试图通过密钥交换(我在帖子中解释的方法)或通过证书获取令牌。 你检查了吗? msdn.microsoft.com/en-us/library/gg327838.aspx 是的。但是该教程仅适用于创建本机客户端应用程序,您始终必须为此提供用户凭据才能检索令牌。我正在尝试使用密钥或证书身份验证来获取令牌,就像 site 在 3 和 7 中解释的那样: 你有什么发现吗? 【参考方案1】:

感谢大家的回答。我终于设法使用 ADAL 3 访问 Dynamics CRM OData API。

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

应用注册

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

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

    输入“姓名”和“登录网址”,网址可以是任何内容(例如https://localhost)

    选择刚刚创建的注册应用,进入Settings\Keys

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

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

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

添加 CRM 应用用户

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

    转到 CRM\Security Roles,创建一个新的安全角色或复制“系统管理员”角色

    转到 CRM\Settings\Security\Users,创建一个新用户,将表单更改为“应用程序用户”

    使用您在上一步中拥有的应用程序 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);

【讨论】:

非常有帮助,您的评论立即解决了我的问题。感谢 Stefan 让我摆脱这种陈规。 如何在java中使用Application Id?【参考方案2】:

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

【讨论】:

您能否分享一些有关您如何使其工作的更多细节?我在同一条船上并尝试使用 client_credentials 授权类型来访问 d365 web api?【参考方案3】:

我建议您查看服务器到服务器 (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

【讨论】:

【参考方案4】:

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

【讨论】:

我尝试使用您建议的 URL,但仍然未获得授权。生成的请求消息是这个,其中令牌被 TOKEN 替换:Method: GET, RequestUri: 'xxxxx.api.crm4.dynamics.com/api/data/v8.1/accounts', Version: 1.1, Content: , Headers: Authorization: Bearer TOKEN 跨度> 您是否尝试下载Manifest并打开JSON文件并找到行:“oauth2AllowImplicitFlow”:false,并将false更改为true并上传文件。【参考方案5】:

我认为您无法绕过向至少某种“集成帐户”提供用户凭据。您可以通过以下方式避免更传统的弹出/重定向 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,它允许您创建应用程序用户。

【讨论】:

【参考方案6】:

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

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

【讨论】:

我确实设置了一个具有相同应用程序 ID 和适当安全角色的应用程序用户。我可以使用 oauth 客户端凭据授予创建不记名令牌,但是当我尝试使用它时,我得到 401 未授权。完全不确定我做错了什么。

远程服务器返回错误:(401) Unauthorized。使用 Paypal Rest APi 时

】远程服务器返回错误:(401)Unauthorized。使用PaypalRestAPi时【英文标题】:Theremoteserverreturnedanerror:(401)Unauthorized.whileusingPaypalRestAPi【发布时间】:2017-01-2502:46:09【问题描述】:我正在使用PaypalRestAPi。当我尝试获取访问令牌时,它... 查看详情

PayPal Rest API - 创建发票时出现 401

...题描述】:我在尝试创建PayPal发票时收到401错误。我正在使用nodejsRESTAPI:https://github.com/paypal/rest-api-sdk-nodejs我对创建发票示例进行了快速测试,将configure.js中的 查看详情

尝试访问 REST API 时出现 401(未授权)

...当我尝试连接时,都会收到401(未经授权)错误。我正在使用C#控制台应用程序对此进行测试,并且我还尝试使用PUTMAN(GoogleChrome应用程序来查看HTTP 查看详情

Cosmos db Rest API - 错误 401 未经授权

...【发布时间】:2019-06-2808:38:19【问题描述】:我正在尝试使用RESTAPI获取对dbcosmos的获取请求!azurecosmosdb有一个特定的标题,但我认为一切都是正确的但是,当我使用HttpRESTAPI时,我收到错误Unauthorized401,你能帮帮我吗?@Overri 查看详情

在 PHP 中使用 curl 访问 REST API 时出现错误 401

】在PHP中使用curl访问RESTAPI时出现错误401【英文标题】:Error401usingcurlinPHPtoaccessRESTAPI【发布时间】:2012-02-2714:24:24【问题描述】:我正在尝试执行一个curl命令,该命令可以在终端中成功执行,但在PHP脚本中失败并出现以下错误... 查看详情

Thingsboard REST api 始终以状态 401 响应

...tus401【发布时间】:2017-03-2719:30:03【问题描述】:首先我使用curl命令获得了一个令牌,如here所示。然后用这个token授权swagger,尝试了一些endpoints,但是都回复了"status":401,"message":"Authenticationf 查看详情

使用spring security angular和rest API重新加载页面给我错误401

】使用springsecurityangular和restAPI重新加载页面给我错误401【英文标题】:reloadingpagegivemeerror401usingspringsecurityangularandrestAPI【发布时间】:2020-06-2204:32:12【问题描述】:我使用SpringBoot、SpringSecurity和Angular客户端进行了相对简单的设... 查看详情

Xampp + Wordpress Rest API(401 代码:rest_cannot_create)

...】:2020-07-2016:03:00【问题描述】:我想实现什么?-我想使用wordpressrestapi为我的自定义帖子类型创建一个帖子什么Api路线有问题?-http://localhost/proftaak/ 查看详情

访问 PayPal 沙箱 Rest API 时响应 401

...://api.sandbox.paypal.com/v1/oauth2/token请求访问令牌并发送POST以使用给定的访问令牌在https://api.sandbox.paypal.com/v1/payme 查看详情

无法使用 rest api 和 python 获取并发布到 alm。总是得到 401 状态码

】无法使用restapi和python获取并发布到alm。总是得到401状态码【英文标题】:Notabletogetandposttoalmusingrestapiandpython.Alwaysgetting401statuscode【发布时间】:2020-05-0707:57:59【问题描述】:我正在使用restapi和python自动化alm。我现在所能做的... 查看详情

使用 Swift(使用 SwiftJWT)和 REST API 连接到 Apple Store Connect - 失败并出现 401

】使用Swift(使用SwiftJWT)和RESTAPI连接到AppleStoreConnect-失败并出现401【英文标题】:ConnectingtoAppleStoreConnectusingSwift(withSwiftJWT)andRESTAPI\'s-failingwith401【发布时间】:2021-07-0915:51:05【问题描述】:我正在尝试通过他们的RESTAPI连接到App... 查看详情

Dynamics CRM 2016 Online Rest API 与客户端凭据 OAuth 流

】DynamicsCRM2016OnlineRestAPI与客户端凭据OAuth流【英文标题】:DynamicsCRM2016OnlineRestAPIwithclientcredentialsOAuthflow【发布时间】:2016-08-2717:46:47【问题描述】:我正在尝试使用DynamicsCRM2016Online和AzureActiveDirectory进行身份验证。我能够按照这... 查看详情

grails spring security rest /api/login 401 Unauthorized

...】:【发布时间】:2017-06-2506:28:12【问题描述】:我已经使用spring-security-core:2.0.0+spring-security-rest:1.4.1插件配置了一个Grails(2.3.7)应用程序为了有两种身份验证类型,一种用于网络的有状态身份验证,一种用于使用令牌(无状态)... 查看详情

PayPal 401 未经授权在实时制作中使用 .NET REST API for Express checkout API 进行信用卡支付

】PayPal401未经授权在实时制作中使用.NETRESTAPIforExpresscheckoutAPI进行信用卡支付【英文标题】:PayPal401Unauthorizedwithcreditcardpaymentinliveproductionusing.NETRESTAPIforExpresscheckoutAPI【发布时间】:2018-02-2615:26:49【问题描述】:我正在使用.NETREST... 查看详情

PayPal REST API - 沙盒为 API 请求返回 401 但访问令牌成功

...stoken【发布时间】:2013-08-2119:47:32【问题描述】:我正在使用Java中的PayPalRESTAPI向测试(沙盒)服务器发出请求以获取访问令牌,该请求成功,然后将该访问令牌发送回相同的沙盒服务器以进行支 查看详情

PayPal Rest API 在切换到 Live Credentials 时出现 401 错误

...其中实现了PayPalRESTAPI来处理信用卡结账。现在的问题是使用SandboxCredentials可以正常工作...但是当我切换到Liv 查看详情

Ejabberd OAuth / REST 401 未经授权

...【发布时间】:2016-02-0908:52:40【问题描述】:我正在尝试使用/api/connected_users端点请求EjabberdRESTWeb服务,但该请求总是返回401UnauthorizedHTTP错误。这是我的OAuth配置。-port:5280module:ejabberd_httpr 查看详情

通过 Axios 和有效 JWT 发布时,WordPress REST API 返回 401 Unauthorized

...【发布时间】:2019-06-1721:04:01【问题描述】:我正在尝试使用Axios和JWT通过我的Vue/Nuxt应用程序将表单中的数据发布到WordPressRESTAPI。我 查看详情