【问题标题】:AcquireTokenAsync method - Unable to get the token using ClientCredentials inAcquireTokenAsync 方法 - 无法使用 ClientCredentials 获取令牌
【发布时间】:2017-11-29 07:42:51
【问题描述】:

这里我想从 CRM 中检索数据并在 Azure 中注册以获取客户凭据并在以下代码中使用它:

using Microsoft.Crm.Sdk.Messages;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.WebServiceClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CRM_WebAPI_Test1
{
    class Program
    {
        static void Main(string[] atrgs)
        {
            MainAsync();
        }
        static async void MainAsync()
        {
            try
            {
                string organizationUrl = "https://OrgName<<URL>>.com";
                string clientId = "xxxxxxxxx-xxxx-xxxx-b7ca-xxxx";
                string clientSecret = "key received from Azure App Registration";
                string aadInstance = "https://login.microsoftonline.com/";
                string tenantID = "orgname";

                ClientCredential clientCredentials = new ClientCredential(clientId, clientSecret);
                AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID);
                AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(organizationUrl, clientCredentials);
                var requestedToken = authenticationResult.AccessToken;

                using (var sdkService = new OrganizationWebProxyClient(GetServiceUrl(organizationUrl), false))
                {
                    sdkService.HeaderToken = requestedToken;

                    OrganizationRequest request = new OrganizationRequest()
                    {
                        RequestName = "WhoAmI"
                    };

                    WhoAmIResponse response = sdkService.Execute(new WhoAmIRequest()) as WhoAmIResponse;
                    Console.WriteLine(response.UserId);

                    Console.WriteLine("Press any key to exit...");
                    Console.ReadLine();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());

                Console.WriteLine("Press any key to exit...");
                Console.ReadLine();
            }
        }
        static private Uri GetServiceUrl(string organizationUrl)
        {
            return new Uri(organizationUrl + @"/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2");
        }
    }
}

但是说到线:

AuthenticationResult authenticationResult = 等待 authenticationContext.AcquireTokenAsync(organizationUrl, 客户凭证);

它直接存在于程序中,不给出任何输出,甚至没有碰到catch异常部分。我在这里有什么遗漏吗?

另外,在 Azure AD 中注册应用程序时如何知道租户名称?

更新: [有问题的更新,因为无法在评论部分写下整个错误,所以请坦白。]根据建议应用代码更改后,它会抛出如下错误:

Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: AADSTS50001:名为 https://orgname.com 的应用程序是 在名为 mydirectory.onmicrosoft.com 的租户中找不到。这个可以 如果管理员尚未安装应用程序,则会发生这种情况 租户的任何用户或租户中的任何用户同意。你可能 已将您的身份验证请求发送给错误的租户。跟踪 ID: 58b1b994-eac3-4209-b553-4cea6a120500 相关 ID: fb8a3f3a-8b0c-4cea-90fa-88ea6e9a7208 时间戳:2017-11-29 09:09:37Z ---> System.Net.Http.HttpRequestException:响应状态码不表示成功:400(BadRequest)。 ---> Microsoft.IdentityModel.Clients.ActiveDirectory.AdalException: {"error":"invalid_resource","error_description":"AADSTS50001: 在 名为 mydirectory.onmicrosoft.com 的租户。如果 租户管理员未安装应用程序 或租户中的任何用户同意。您可能已经发送了您的 对错误租户的身份验证请求。\r\n跟踪 ID: 58b1b994-eac3-4209-b553-4cea6a120500\r\n相关 ID: fb8a3f3a-8b0c-4cea-90fa-88ea6e9a7208\r\n时间戳:2017-11-29 09:09:37Z","error_codes":[50001],"timestamp":"2017-11-29 09:09:37Z","trace_id":"58b1b994-eac3-4209-b553-4cea6a120500","correlation_id":"fb8a3f3a-8b0c-4cea-90fa-88ea6e9a7208"}: 未知错误---内部异常堆栈跟踪结束---在 Microsoft.IdentityModel.Clients.ActiveDirectory.HttpClientWrapper.d__31.MoveNext() --- 内部异常堆栈跟踪结束 --- 在 Microsoft.IdentityModel.Clients.ActiveDirectory.AdalHttpClient.d__221.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.IdentityModel.Clients.ActiveDirectory.AdalHttpClient.<GetResponseAsync>d__211.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.d__71.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.d__68.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.d__59.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(任务任务)
在 Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.d__57.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.d__33.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.d__58.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 在 CRM_WebAPI_Test1.Program.d__1.MoveNext() 中 E:\VS_2015\CRM 项目\CRM_WebAPI_Test1\CRM_WebAPI_Test1\Program.cs:第 31 行 错误代码:invalid_resource 状态码:400

【问题讨论】:

  • organizationUrl 是否类似于:https://contoso.crm.dynamics.com
  • 不,这是我在我的组织中创建的试用帐户,而不是 contoso.crm 它是不同的,其余相同。
  • 好的,URI 应该是https://yourorganisationname.crm.dynamics.com
  • 正确,但它就像:https://betaversionName.organisationname.com - 我是在通过客户 CRM 中提供的 Service Root URL 确认后写的。
  • 嗯,我不确定服务根 URL 和资源 URI 是否相同。您是否使用 AcquireTokenAsync 尝试了我建议的 URI?

标签: c# azure microsoft-dynamics dynamics-365


【解决方案1】:

首先,您正在使用 async void 函数,这是您不应该使用的(除非在您不能影响方法签名的事件处理程序中)。

所以应该是这样的:

static void Main(string[] atrgs)
{
    MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
}

基本上在您的代码中,当它遇到等待时,它会返回到 Main 并且程序退出。

在 C# 7.2 中,您还可以将 main 方法声明为 async Task,因此您可以只使用 await 方法。

您可以从 Azure 门户获取租户 id

  1. 打开 Azure AD 刀片
  2. 转到属性
  3. 可以找到租户id

另一种选择是使用任何经过验证的域名(例如 mydirectory.onmicrosoft.com)。

【讨论】:

  • 代码建议解决了我的第一个问题,但之后它抛出了问题中更新的错误。
猜你喜欢
  • 2021-09-15
  • 1970-01-01
  • 2013-08-23
  • 1970-01-01
  • 2019-02-15
  • 2017-11-17
  • 2017-05-13
  • 1970-01-01
  • 2019-10-26
相关资源
最近更新 更多