我发现要成功执行此操作,您需要设置以下所有内容:
- 在 Azure AD 中创建应用程序注册:
- 授予它对 Dynamics 的 API 权限,特别是“以组织用户身份访问 Dynamics 365”
- 给它一个虚拟的 Web 重定向 URI,例如
http://localhost/auth
- 生成客户端密码并保存以备后用
- 在 Azure AD 中创建一个用户帐户并为其授予对 Dynamics 的权限。
- 使用与上述非交互式用户帐户相同的电子邮件在 Dynamics 中创建应用程序用户记录。
- 使用您创建的用户帐户验证您的应用程序。
对于第 4 步,您需要打开一个新的隐身窗口,使用以下模式构建一个 url,并在第 2 步中使用您的用户帐户凭据登录:
https://login.microsoftonline.com/<your aad tenant id>/oauth2/authorize?client_id=<client id>&response_type=code&redirect_uri=<redirect uri from step 1>&response_mode=query&resource=https://<organization name>.<region>.dynamics.com&state=<random value>
完成后,您应该会看到您的 Dynamics 应用程序用户具有应用程序 ID 和应用程序 ID URI。
现在使用您的 ClientId 和 ClientSecret 以及其他一些组织特定变量,您可以使用 Azure Active Directory (AAD) 进行身份验证以获取 oauth 令牌并构造一个OrganizationWebProxyClient
. 我从来没有找到这样做的完整代码示例,但我出于自己的目的开发了以下代码。请注意,您获得的令牌的有效期为 1 小时。
internal class ExampleClientProvider
{
// Relevant nuget packages:
// <package id="Microsoft.CrmSdk.CoreAssemblies" version="9.0.2.9" targetFramework="net472" />
// <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="4.5.1" targetFramework="net461" />
// Relevant imports:
// using Microsoft.IdentityModel.Clients.ActiveDirectory;
// using Microsoft.Crm.Sdk.Messages;
// using Microsoft.Xrm.Sdk;
// using Microsoft.Xrm.Sdk.Client;
// using Microsoft.Xrm.Sdk.WebServiceClient;
private const string TenantId = "<your aad tenant id>"; // from your app registration overview "Directory (tenant) ID"
private const string ClientId = "<your client id>"; // from your app registration overview "Application (client) ID"
private const string ClientSecret = "<your client secret>"; // secret generated in step 1
private const string LoginUrl = "https://login.microsoftonline.com"; // aad login url
private const string OrganizationName = "<your organization name>"; // check your dynamics login url, e.g. https://<organization>.<region>.dynamics.com
private const string OrganizationRegion = "<your organization region>"; // might be crm for north america, check your dynamics login url
private string GetServiceUrl()
{
return $"{GetResourceUrl()}/XRMServices/2011/Organization.svc/web";
}
private string GetResourceUrl()
{
return $"https://{OrganizationName}.api.{OrganizationRegion}.dynamics.com";
}
private string GetAuthorityUrl()
{
return $"{LoginUrl}/{TenantId}";
}
public async Task<OrganizationWebProxyClient> CreateClient()
{
var context = new AuthenticationContext(GetAuthorityUrl(), false);
var token = await context.AcquireTokenAsync(GetResourceUrl(), new ClientCredential(ClientId, ClientSecret));
return new OrganizationWebProxyClient(new Uri(GetServiceUrl()), true)
{
HeaderToken = token.AccessToken,
SdkClientVersion = "9.1"
};
}
public async Task<OrganizationServiceContext> CreateContext()
{
var client = await CreateClient();
return new OrganizationServiceContext(client);
}
public async Task TestApiCall()
{
var context = await CreateContext();
// send a test request to verify authentication is working
var response = (WhoAmIResponse) context.Execute(new WhoAmIRequest());
}
}