Azure active directory 使用Azure Function app的登录用户验证Dynamics 365 Web Api

Azure active directory 使用Azure Function app的登录用户验证Dynamics 365 Web Api,azure-active-directory,azure-functions,microsoft-dynamics,azure-authentication,microsoft-dynamics-webapi,Azure Active Directory,Azure Functions,Microsoft Dynamics,Azure Authentication,Microsoft Dynamics Webapi,我有一个Azure功能应用程序(HTTP触发器功能),它受Azure AD身份验证保护 当我在我的浏览器中转到函数的URL时,它工作得很好。我首先被重定向到登录页面,在那里我可以使用我的Azure Active Directory登录凭据登录 但是,我希望函数连接到Dynamics 365 Web API,以便使用登录用户的身份读取一些数据。我已经复制了连接到Web API和在Azure中配置应用程序权限的代码。我的Dynamics 365实例与我的Azure以及我与有权访问Dynamics 3

我有一个Azure功能应用程序(HTTP触发器功能),它受Azure AD身份验证保护

当我在我的浏览器中转到函数的URL时,它工作得很好。我首先被重定向到登录页面,在那里我可以使用我的Azure Active Directory登录凭据登录

但是,我希望函数连接到Dynamics 365 Web API,以便使用登录用户的身份读取一些数据。我已经复制了连接到Web API和在Azure中配置应用程序权限的代码。我的Dynamics 365实例与我的Azure以及我与有权访问Dynamics 365的用户一起登录的用户位于同一租户中

我正在努力解决的部分是获取访问令牌来调用与登录用户对应的Dynamics Web API

第一次尝试

然后,根据“X-MS-token-AAD-ID-token”标题,我尝试使用来自当前登录用户的令牌。我的代码如下-它未连接到Dynamics Web API-我收到401-未经授权的响应:

[FunctionName("TestCrmFunction")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
    var crmUrl = "https://myorganisation.crm11.dynamics.com";

    // Get the token from the HTTP header of the request:
    var token = req.Headers
        .Where(x => x.Key == "X-MS-TOKEN-AAD-ID-TOKEN")
        .SelectMany(x => x.Value)
        .FirstOrDefault();

    using (var httpClient = new HttpClient())
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

        httpClient.BaseAddress = new Uri(crmUrl);

        // set the token here:
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var response = await httpClient.GetAsync("api/data/v8.1/WhoAmI");

        var content = await response.Content.ReadAsStringAsync();

        if (response.IsSuccessStatusCode)
        {
            // I don't get here...
            return req.CreateResponse(HttpStatusCode.OK, content);
        }
        else
        {
            // ... I get here
            return req.CreateResponse(response.StatusCode, $"ERROR: {content}");
        }
    }

}
解决方案-不是真正的解决方案

我唯一能做的就是硬编码我登录的用户的用户名/密码:

var credentials = new UserPasswordCredential("<my username>", "<my password>");

AuthenticationResult authenticationResult = await 
authenticationContext.AcquireTokenAsync(crmUrl, clientId, credentials);
var-credentials=newuserpasswordcredential(“,”);
AuthenticationResult AuthenticationResult=等待
AcquireTokenAsync(crmUrl、clientId、凭据);

。。。但这种做法有违目的——通过硬编码用户名/密码,我肯定只是完全绕过了Azure应用程序注册安全性?

这是一种更好的选择,但可能更容易实现

如果您能够以某种方式识别当前用户,例如从令牌读取详细信息。然后,您可以使用服务帐户连接到CRM,但将服务对象设置为模拟用户

模拟用户

要模拟用户,请在的实例上设置CallerId属性 OrganizationServiceProxy,然后调用服务的Web方法

//检索要模拟的用户的系统用户ID。
OrganizationServiceContext orgContext=新的OrganizationServiceContext(\u serviceProxy);
_userId=(来自orgContext.CreateQuery()中的用户)
其中user.FullName==“来自您的令牌的内容”//可能是域名?
选择user.SystemUserId.Value).FirstOrDefault();
//要模拟其他用户,请设置OrganizationServiceProxy.CallerId
//属性设置为其他用户的ID。
_serviceProxy.CallerId=\u userId;

通过连接Azure Function应用程序并为其提供安全凭据来连接到dynamics 365、检索数据、执行一些数据操作,然后将数据写回dynamics 365,我确实做到了同样的事情

请看下面我的帖子,如果它对你的情况有帮助,希望你能将此标记为已回答


如果我错了,请纠正我,但您的答案仍然不是使用刚刚使用function app进行身份验证的同一用户通过dynamics进行身份验证,这就是我的问题所在。您好,您的解决方法是,从哪里获得客户ID?我正在尝试做同样的事情,但当我使用System Assined managed identity作为clientId时失败了。
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: AADSTS50027: Invalid JWT token. AADSTS50027: Invalid JWT token. Token format not valid.
var credentials = new UserPasswordCredential("<my username>", "<my password>");

AuthenticationResult authenticationResult = await 
authenticationContext.AcquireTokenAsync(crmUrl, clientId, credentials);
// Retrieve the system user ID of the user to impersonate.
OrganizationServiceContext orgContext = new OrganizationServiceContext(_serviceProxy);
_userId = (from user in orgContext.CreateQuery<SystemUser>()
          where user.FullName == "Something from your token" //perhaps domain name?
          select user.SystemUserId.Value).FirstOrDefault();

// To impersonate another user, set the OrganizationServiceProxy.CallerId
// property to the ID of the other user.
_serviceProxy.CallerId = _userId;