使用Azure函数中的Dynamics 365进行身份验证

时间:2018-04-27 11:04:06

标签: c# azure dynamics-crm azure-functions dynamics-365

方案

我有一个在线托管的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组织进行身份验证以读取和写入数据?

我尝试了什么

  1. Xrm Tooling
  2. 最简单的身份验证方法是使用Microsoft.Xrm.Tooling.Connector.dll中的CrmServiceClient。但是,我不一定有用户名和密码来提供CrmServiceClient的构造函数。也许凭证可以通过HTTP POST请求安全传递?

    1. 申请用户
    2. 我尝试在Dynamics中注册应用程序用户。我向Azure功能提供客户端ID和客户端密钥,但身份验证失败,因为用户与Azure功能位于不同的租户。

      考虑解决方案

      收到的jsonContent字符串的一个对象称为ParentContext。也许这可以重复用于通过调用Dynamics组织进行身份验证。

      Marc Schweigert建议使用S2S并向他的AzureFunctionApp存储库提供样本。如果我可以使用这种方法,我会在这里发布解决方案。

3 个答案:

答案 0 :(得分:3)

我不会认为您可以合理地使用“真正的”用户凭据连接到CRM。

我会使用服务帐户连接回CRM。创建一个新的CRM 用户尤其是为此目的,如果您使用户非交互式,则不应使用许可证。然后,您可以使用该服务帐户的凭据使用CrmServiceClient连接到CRM。或者看看Server to Server authentication

如果您能够向功能应用提供用户ID,则可以通过CRM网络服务将服务帐户用于impersonate“真实”用户。

  

要模拟用户,请在实例上设置Call​​erId属性   在调用服务的Web方法之前的OrganizationServiceProxy。

答案 1 :(得分:1)

这也是我很好奇的事情,但我没有机会对此进行实验。

对于您的第二种选择,您是否已在目标AAD中注册申请并获得同意?

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/use-multi-tenant-server-server-authentication

  

当他们同意时,您注册的应用程序将被添加到Azure AD企业应用程序列表中,并且Azure AD租户的用户可以使用它。

     

只有在管理员授予同意后,您才必须在订阅者的Dynamics 365租户中创建应用程序用户

我认为访问问题的根源与应用程序的服务主体对象(目标租户的本地对象)有关

服务主体对象

https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-application-objects#service-principal-object

  

要访问由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);