我有一个在线托管的Dynamics 365 v9组织。我在Azure功能应用程序中托管了一组Azure功能,这些功能位于我的Dynamics组织的不同租户中。
我使用动态插件注册工具创建了web hooks,在某些事件中(例如在Dynamics中创建联系人时),通过其端点URL将数据发布到我的Azure功能。
Dynamics 365和我的Azure功能之间的身份验证是通过在HTTP请求的身份验证HttpHeader中传递x-functions-key
值来实现的。
Azure Functions以RemoteExecutionContext的形式从Dynamics中的事件接收数据,我可以使用以下代码阅读:
using System.Net;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
var jsonContent = await req.Content.ReadAsStringAsync();
log.Info(jsonContent);
return req.CreateResponse(HttpStatusCode.OK);
}
然后,Azure功能如何通过调用Dynamics 365组织进行身份验证以读取和写入数据?
最简单的身份验证方法是使用Microsoft.Xrm.Tooling.Connector.dll中的CrmServiceClient。但是,我不一定有用户名和密码来提供CrmServiceClient的构造函数。也许凭证可以通过HTTP POST请求安全传递?
我尝试在Dynamics中注册应用程序用户。我向Azure功能提供客户端ID和客户端密钥,但身份验证失败,因为用户与Azure功能位于不同的租户。
收到的jsonContent
字符串的一个对象称为ParentContext
。也许这可以重复用于通过调用Dynamics组织进行身份验证。
Marc Schweigert建议使用S2S并向他的AzureFunctionApp存储库提供样本。如果我可以使用这种方法,我会在这里发布解决方案。
答案 0 :(得分:3)
我不会认为您可以合理地使用“真正的”用户凭据连接到CRM。
我会使用服务帐户连接回CRM。创建一个新的CRM
用户尤其是为此目的,如果您使用户非交互式,则不应使用许可证。然后,您可以使用该服务帐户的凭据使用CrmServiceClient
连接到CRM。或者看看Server to Server authentication。
如果您能够向功能应用提供用户ID,则可以通过CRM网络服务将服务帐户用于impersonate“真实”用户。
要模拟用户,请在实例上设置CallerId属性 在调用服务的Web方法之前的OrganizationServiceProxy。
答案 1 :(得分:1)
这也是我很好奇的事情,但我没有机会对此进行实验。
对于您的第二种选择,您是否已在目标AAD中注册申请并获得同意?
当他们同意时,您注册的应用程序将被添加到Azure AD企业应用程序列表中,并且Azure AD租户的用户可以使用它。
只有在管理员授予同意后,您才必须在订阅者的Dynamics 365租户中创建应用程序用户。
我认为访问问题的根源与应用程序的服务主体对象(目标租户的本地对象)有关
服务主体对象
要访问由Azure AD租户保护的资源,需要访问权限的实体必须由安全主体表示。对于用户(用户主体)和应用程序(服务主体)都是如此。安全主体定义该租户中的用户/应用程序的访问策略和权限。这样可以实现核心功能,例如在登录期间对用户/应用程序进行身份验证,以及在资源访问期间进行授权。
将应用程序对象视为应用程序的全局表示形式,以便在所有租户中使用,并将服务主体视为在特定租户中使用的本地表示形式。
HTH
-Chris
答案 2 :(得分:1)
使用S2S,您可以使用AcquireToken来检索Bearer
var clientcred = new ClientCredential(clientId, clientSecret);
AuthenticationContext authContext = new AuthenticationContext(aadInstance, false);
AuthenticationResult result = authContext.AcquireToken(organizationUrl, clientcred);
token = result.AccessToken;
ExpireDate = result.ExpiresOn.DateTime;
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);