Dynamics crm Dynamics客户参与Web API的应用程序权限支持

Dynamics crm Dynamics客户参与Web API的应用程序权限支持,dynamics-crm,dynamics-crm-online,dynamics-365,Dynamics Crm,Dynamics Crm Online,Dynamics 365,我们计划从组织服务转移到,这样我们就可以利用OAuth 2.0身份验证,而不是客户有一些安全顾虑的服务帐户 一旦我们做了一些原型,我们发现WebAPI认证与典型的GraphAPI认证有点不同。它只支持委托权限。因此,必须提供用户凭证以获取访问令牌 以下是CRM Web API的Azure AD Graph API权限: 下面是获取访问令牌的代码 这是另一个类似的帖子,虽然已经有一年多了 您知道MS何时会支持应用程序权限以完全消除用户的身份验证吗?或者有任何特殊的原因让用户留在这里。谢谢你的见解

我们计划从组织服务转移到,这样我们就可以利用OAuth 2.0身份验证,而不是客户有一些安全顾虑的服务帐户

一旦我们做了一些原型,我们发现WebAPI认证与典型的GraphAPI认证有点不同。它只支持委托权限。因此,必须提供用户凭证以获取访问令牌

以下是CRM Web API的Azure AD Graph API权限:

下面是获取访问令牌的代码

这是另一个类似的帖子,虽然已经有一年多了

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

[更新1] 下面是James的回答,我修改了代码,这是我的代码

        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);
        }
    }
顺便说一下,我们已经按照说明在CRM中创建了应用程序用户

我有什么遗漏吗

[更新2] 对于WhoAmI请求,有不同的结果。如果我使用的是最新的且具有权限的“”,我将能够得到正确的结果。如果我将MSAL与“”一起使用,它将无法工作,我将收到未经授权的错误。如果我使用的是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);
        }

文档不是最容易理解的,但据我所知,您应该从开始

在注册应用程序时,您有两个微妙的选择。第二个不需要Access Dynamics 365/公共数据服务作为组织用户权限

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

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

这一点将进一步阐述

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

注册你的应用程序

注册应用程序时,请遵循许多相同的步骤。。。和 下列例外情况:

  • 您不需要授予Access Dynamics 365 as organization users权限
在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;
您可能还想查看一个类似(但不同)的

使用服务器到服务器(S2S)身份验证安全无缝地 使用web应用程序和通用数据服务进行通信 服务。S2S身份验证是应用程序注册的常用方式 Microsoft AppSource用于访问的公用数据服务数据 他们的订户。。。应用程序不是基于用户凭据,而是基于由存储在应用程序用户记录中的Azure AD对象ID值标识的服务主体进行身份验证

旁白;如果您当前正在使用Organization Service.NET对象,则该对象将迁移到内部使用Web API

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


谢谢James,请根据您的建议查看我的问题更新。您是否尝试过直接向Dynamics实例提交WhoAmI请求?谢谢@JamesWood,请查看上面的更新2。
            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);
        }
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)
    {
    ...
    }
}