【问题标题】:Application Permission support for Dynamics Customer Engagement Web APIDynamics Customer Engagement Web API 的应用程序权限支持
【发布时间】:2019-08-12 14:36:50
【问题描述】:

我们计划从组织服务迁移到Common Data Service Web API,因此我们可以使用 OAuth 2.0 身份验证,而不是客户存在一些安全问题的服务帐户。

一旦我们做了一些原型,我们发现 Web API 身份验证与典型的 Graph API 身份验证有点不同。它仅支持委托权限。因此,必须提供用户凭证才能获取访问令牌。

这是 CRM Web API 的 Azure AD Graph API 权限:

这里是在Web API Global Discovery Service Sample (C#)获取示例代码的访问令牌的代码

  string GlobalDiscoUrl = "https://globaldisco.crm.dynamics.com/";
  AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com", false);

  UserCredential cred = new UserCredential(username, password);
  AuthenticationResult authResult = authContext.AcquireToken(GlobalDiscoUrl, clientId, cred);

这是另一篇类似的帖子Connect to Dynamics 365 Customer Engagement web services using OAuth,尽管它已有一年多的历史了。

您知道 MS 什么时候会支持应用程序权限以完全消除用户的身份验证吗?或者有任何特殊原因将用户留在这里。感谢您的任何见解。

[更新 1] 根据詹姆斯的以下回答,我对代码进行了修改,这是我的代码

        string clientId = "3f4b24d8-61b4-47df-8efc-1232a72c8817";
        string secret = "xxxxx";

        ClientCredential cred = new ClientCredential(clientId, secret);
        string GlobalDiscoUrl = "https://globaldisco.crm.dynamics.com/";
        AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/common", false);


        AuthenticationResult authResult = authContext.AcquireToken(GlobalDiscoUrl, cred);

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        client.Timeout = new TimeSpan(0, 2, 0);
        client.BaseAddress = new Uri(GlobalDiscoUrl);

        HttpResponseMessage response = client.GetAsync("api/discovery/v1.0/Instances", HttpCompletionOption.ResponseHeadersRead).Result;


        if (response.IsSuccessStatusCode)
        {
            //Get the response content and parse it.
            string result = response.Content.ReadAsStringAsync().Result;
            JObject body = JObject.Parse(result);
            JArray values = (JArray)body.GetValue("value");

            if (!values.HasValues)
            {
                return new List<Instance>();
            }

            return JsonConvert.DeserializeObject<List<Instance>>(values.ToString());
        }
        else
        {
            throw new Exception(response.ReasonPhrase);
        }
    }

所以我能够获取访问令牌,但它仍然无法访问全局发现服务。

访问令牌如下所示:

    {
  "aud": "https://globaldisco.crm.dynamics.com/",
  "iss": "https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/",
  "iat": 1565802457,
  "nbf": 1565802457,
  "exp": 1565806357,
  "aio": "42FgYEj59uDNtwvxTLnprU0NYt49AA==",
  "appid": "3f4b24d8-61b4-47df-8efc-1232a72c8817",
  "appidacr": "1",
  "idp": "https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/",
  "tid": "f8cdef31-a31e-4b4a-93e4-5f571e91255a",
  "uti": "w8uwKBSPM0y7tdsfXtAgAA",
  "ver": "1.0"
}

顺便说一句,我们已经按照说明在 CRM 中创建了应用程序用户。

我在这里缺少什么?

[更新 2] 对于 WhoAmI 请求,有不同的结果。如果我使用最新的MSAL 并具有权限“https://login.microsoftonline.com/AzureADDirectoryID/oauth2/authorize”,我将能够得到正确的结果。如果我将 MSAL 与“https://login.microsoftonline.com/common/oauth2/authorize”一起使用,它将不起作用,我会收到未经授权的错误。如果我使用ADAL 2.29,它对这两个权限都不起作用。这是工作代码:

            IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create("3f4b24d8-61b4-47df-8efc-1232a72cxxxx")
            .WithClientSecret("xxxxxx")
          //  .WithAuthority("https://login.microsoftonline.com/common/oauth2/authorize", false)  
            .WithAuthority("https://login.microsoftonline.com/3a984a19-7f55-4ea3-a422-2d8771067f87/oauth2/authorize", false)
            .Build();

        var authResult = app.AcquireTokenForClient(new String[] { "https://crmxxxxx.crm5.dynamics.com/.default" }).ExecuteAsync().Result;

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        client.Timeout = new TimeSpan(0, 2, 0);
        client.BaseAddress = new Uri("https://crm525842.api.crm5.dynamics.com/");

        HttpResponseMessage response = client.GetAsync("api/data/v9.1/WhoAmI()", HttpCompletionOption.ResponseHeadersRead).Result;


        if (response.IsSuccessStatusCode)
        {
            //Get the response content.
            string result = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }
        else
        {
            throw new Exception(response.ReasonPhrase);
        }

【问题讨论】:

  • 您是否尝试过直接向您的 Dynamics 实例提交 WhoAmI 请求?
  • 感谢@JamesWood,请检查上面的更新 2。

标签: dynamics-crm dynamics-crm-online dynamics-365


【解决方案1】:

文档不是最容易理解的,但据我了解,您应该从 Use OAuth with Common Data Service 开始。

然后,在注册您的应用时,您有两个微妙的选择。第二种不需要 Access Dynamics 365/Common Data Service 作为组织用户权限

Giving access to Common Data Service

如果您的应用程序将是允许经过身份验证的用户的客户端 执行操作,您必须将应用程序配置为具有 以组织用户委派权限的身份访问 Dynamics 365。

或者

如果您的应用将使用服务器到服务器 (S2S) 身份验证,请执行此步骤 不需要。该配置需要特定的系统用户 并且操作将由该用户帐户执行,而不是 任何必须经过身份验证的用户。

这将进一步阐述。

Connect as an app

您将创建的某些应用程序并非旨在以交互方式运行 一个用户。 ...在这些情况下,您可以创建一个特殊的应用程序用户 绑定到 Azure Active Directory 注册的应用程序和 使用为应用程序配置的密钥或上传 X.509 证书。这种方法的另一个好处是它不 使用付费许可证。

注册您的应用

注册应用程序时,您遵循许多相同的步骤...... 以下例外:

  • 您无需授予 Access Dynamics 365 作为组织用户权限

您仍将在 Dynamics 中拥有一个系统用户记录来代表应用程序注册。这支持一系列基本的 Dynamics 行为,并允许您将 Dynamics 安全性应用于您的应用程序。

与用户名和密码相反,您可以使用密码进行连接。

string serviceUrl = "https://yourorg.crm.dynamics.com";
string clientId = "<your app id>";
string secret = "<your app secret>";

AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/common", false);
ClientCredential credential = new ClientCredential(clientId, secret);

AuthenticationResult result = authContext.AcquireToken(serviceUrl, credential);

string accessToken = result.AccessToken;

或者证书。

string CertThumbPrintId = "DC6C689022C905EA5F812B51F1574ED10F256FF6";
string AppID = "545ce4df-95a6-4115-ac2f-e8e5546e79af";
string InstanceUri = "https://yourorg.crm.dynamics.com";

string ConnectionStr = $@"AuthType=Certificate;
                        SkipDiscovery=true;url={InstanceUri};
                        thumbprint={CertThumbPrintId};
                        ClientId={AppID};
                        RequireNewInstance=true";
using (CrmServiceClient svc = new CrmServiceClient(ConnectionStr))
{
    if (svc.IsReady)
    {
    ...
    }
}

您可能还想查看Build web applications using Server-to-Server (S2S) authentication,它看起来很相似(但不同)。

使用服务器到服务器 (S2S) 身份验证来安全、无缝地进行 通过您的 Web 应用程序与 Common Data Service 进行通信,以及 服务。 S2S 身份验证是应用注册的常用方式 Microsoft AppSource 用于访问 Common Data Service 的数据 他们的订阅者。 ...不是用户凭据,而是基于存储在应用程序用户记录中的 Azure AD 对象 ID 值标识的服务主体对应用程序进行身份验证。

一边;如果您当前使用的是组织服务 .NET 对象,则该对象正在迁移到内部使用 Web API。

Microsoft Dynamics CRM 2011 endpoint

Dynamics 365 SDK 程序集将更新为使用 Web API。 此更新将对您和编写的任何代码完全透明 将支持使用 SDK 本身。

【讨论】:

  • 谢谢詹姆斯,请根据您的建议在这里查看我对问题的更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 2021-06-07
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多