【问题标题】:How do I call 3rd party REST service from Dynamics 365 CRM online?如何从 Dynamics 365 CRM Online 调用第 3 方 REST 服务?
【发布时间】:2019-08-30 06:57:00
【问题描述】:

我知道this 的问题几乎相同,但我需要使用访问令牌来保护通话。

因此,当从 Dynamics 365 CRM online 调用外部 Web api 时,我需要使用 Bearer 令牌设置授权请求标头。

如何获取访问令牌以随通话发送?

编辑: 我们正在使用 Azure Ad 在线登录 Dynamics 365 CRM,此时我们会收到一个保存在 cookie 中的令牌。

当我们调用外部 web api 时,我们希望将该令牌与我们的调用一起作为 Authorization 标头发送。

编辑:

我们已尝试创建插件/活动 (C#),但在该上下文中没有 cookie 集合(我们可以看到)。在下面的示例中,我们尝试使用 clientid 和 clientcredentials,但其中不涉及用户信息。

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;

namespace MyPlugin
{
    public class TestPlugin : IPlugin
    {
        private const string ClientId = "***";
        private const string ClientSecret = "***";
        private const string AadInstance = "https://login.microsoftonline.com/";
        private const string TenantId = "***";
        private const string PostLogoutRedirectUri = "https://***.crm4.dynamics.com";

        public void Execute(IServiceProvider serviceProvider)
        {
            var tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            var accessToken = GetTokenWithoutAdal().GetAwaiter().GetResult();
            tracer.Trace(accessToken);

            RetrieveAccounts(accessToken).GetAwaiter().GetResult();
        }

        private static async Task<string> GetTokenWithoutAdal()
        {
            var loginUrl = AadInstance + $"{TenantId}/oauth2/token";

            var client = new HttpClient();
            var postData = $"client_id={ClientId}&client_secret={ClientSecret}&resource={PostLogoutRedirectUri}&grant_type=client_credentials";

            var request = new HttpRequestMessage(HttpMethod.Post, loginUrl) { Content = new StringContent(postData, Encoding.UTF8) };

            request.Content.Headers.Remove("Content-Type");
            request.Content.Headers.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            var responseMessage = await client.SendAsync(request);

            var jsonResponseString = await responseMessage.Content.ReadAsStringAsync();

            string something = null;
            //Do something

            return something;
        }

        private static async Task<string> RetrieveAccounts(string token)
        {
            var webApiUrl = "https://***.test.com/v1.0";
            var url = $"{webApiUrl}/accounts";

            var client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            var response = await client.GetAsync(url);

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

            return jsonContent;
        }
    }
}

同事也试过用Javascript调用LogicApp,但没有发送token。

function callLogicApp() {
    fetch('https://dynamicstestapi.azure-api.net/manual/paths/invoke',
            {
                method: 'POST',
                body: JSON.stringify({
                    title: 'foo',
                    body: 'bar',
                    userId: 1
                }),
                credentials: 'include',
                mode: 'cors',
                headers: {
                    'Content-type': 'application/json; charset=UTF-8',
                    'Ocp-Apim-Subscription-Key': 'e1e884bbe9a945a9a4dbcabff49e59d8'
                }
            })
        .then(res => res.json())
        .then(console.log);
}

编辑:

这就是我想要的,用户访问令牌(仅来自 JWT 的有效负载)

{
  "aud": "https://myapi.net",
  "iss": "https://sts.windows.net/******-****-4c1e-b346-2a28ef579dea/",
  "iat": 1567158525,
  "nbf": 1567158525,
  "exp": 1567162425,
  "acr": "1",
  "aio": "ASQA2/8MAAAA1czfs/LOnB0mRwLY****ZF4tHvcoN+oOwpFUE1F6cgU=",
  "amr": [
    "pwd"
  ],
  "appid": "6792c685-bbf7-****-b15f-7b047edd2db6",
  "appidacr": "1",
  "family_name": "Lastname",
  "given_name": "Firstname",
  "ipaddr": "194.114.***.***",
  "name": "Firstname Lastname",
  "oid": "0ba39690-fb32-****-8d6c-3e4826b2f05b",
  "puid": "10030000826E****",
  "scp": "Directory.Read.All User.Read",
  "sub": "3C04Virz0afCxbAfY5****YfNgnC9HR7y3Mqcbgu5wg",
  "tenant_region_scope": "EU",
  "tid": "6f310cfb-5ece-****-b346-2a28ef579dea",
  "unique_name": "fname.lname@domain.com",
  "upn": "fname.lname@domain.com",
  "uti": "U9v1VNGnY0i****-wHlCAA",
  "ver": "1.0"
}

这是我可以通过 clientid 和 clientsecret 获得的(仅来自 JWT 的有效负载)

{
  "aud": "https://myapi.net",
  "iss": "https://sts.windows.net/******-****-4c1e-b346-2a28ef579dea/",
  "iat": 1567161484,
  "nbf": 1567161484,
  "exp": 1567165384,
  "aio": "42FgYKhpmv0+****3SV/FZvuDbduAA==",
  "appid": "3401bb09-a6f2-****-846a-ef4570b3a8bd",
  "appidacr": "1",
  "idp": "https://sts.windows.net/******-****-4c1e-b346-2a28ef579dea/",
  "oid": "125746e6-4f03-****-8cf9-d568b9fce035",
  "sub": "125746e6-4f03-****-8cf9-d568b9fce035",
  "tid": "6f310cfb-5ece-****-b346-2a28ef579dea",
  "uti": "QiEIwm3560-****ZLz4RAA",
  "ver": "1.0"
}

【问题讨论】:

  • 如何获取访问令牌以随通话发送?什么访问令牌?
  • 这个问题与 Azure 有什么关系?
  • @PatrickHofman,我已经编辑了我的问题,这有帮助吗?
  • 通常在调用外部 API 时,您会使用某种静态凭据(即客户端 ID 和机密),这些凭据要么是硬编码的,要么存储在数据库中并由插件检索。然后,您可以利用诸如 RestSharp 之类的现有框架来构建带有身份验证标头的请求。您能否解释一下您的 CRM 登录凭据与此 API 调用有何关联?
  • 您在插件中没有上下文来检索任何类型的客户端信息,例如 AD 身份验证凭据或 cookie。您确实拥有执行系统用户的 ID,并且您可以构建一个包含此 ID 的标头以进行身份​​验证。

标签: javascript c# azure oauth dynamics-crm


【解决方案1】:

我意识到我的客户实际上想要混合身份验证/自动化和跟踪。

我们还从 Microsoft 得到确认,无法在线检索 D365 中的用户访问令牌并将其与调用一起发送到 3rd 方休息服务。

【讨论】:

    猜你喜欢
    • 2018-02-07
    • 2020-01-17
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多