Dynamics 365 for Operations SPA和OData

时间:2017-10-31 19:36:44

标签: azure authentication microsoft-dynamics operations dynamics-365

我正在尝试创建一个单页Web应用程序,通过Azure AD对Dynamics 365 for Operations进行身份验证。我已按照所有说明在Azure AD和Dynamics 365中注册我的应用程序。我已成功通过Azure AD进行身份验证,并使用adal javascript库在我的应用程序中收到了有效令牌,但是,当我在D365中向OData端点发出请求时,我收到401错误。我已通过Azure AD进行身份验证,并且我在身份验证标头中传递了令牌,因此我无法弄清楚为什么我收到身份验证错误,除非我可能没有正确设置我的授权标头?这是我的要求:

//Function that actually retrieves the accounts
function retrieveAccounts(error, token) {
// Handle ADAL Errors.
if (error || !token) {
    errorMessage.textContent = 'ADAL error occurred: ' + error;
    return;
}

var req = new XMLHttpRequest()
req.open("GET", encodeURI(organizationURI + "/data/Projects"), true);
//Set Bearer token
req.setRequestHeader("Authorization", "Bearer" + token);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
    if (this.readyState == 4 /* complete */) {
        req.onreadystatechange = null;
        if (this.status == 200) {
            var projects = JSON.parse(this.response).value;
            renderProjects(projects);
        }
        else {
            var error = JSON.parse(this.response).error;
            console.log(error.message);
            errorMessage.textContent = error.message;
        }
    }
};
req.send();
}  

任何想法都将不胜感激!我能够使用web api成功地使用Dynamics 365 CRM,所以我假设它也适用于Operations,即使设置稍有不同。

3 个答案:

答案 0 :(得分:1)

我也面临着同样的问题,但是经过研究后,我终于成功使用Web API与CRM集成了。

尝试使用此过程:-

    int                             find;
    real                            inventOnHandQtyval;
    str                             url,aosUri,activeDirectoryTenant;
    str                             activeDirectoryClientAppId;
    str                             activeDirectoryClientAppSecret,json;
    str                             postData,activeDirectoryResource;
    str                             aadClientAppSecret,oAuthHeader;
    str                             prdGUIDCode,prodnum;
    str                             returnValue,jsonString,jsondszstr;

    System.Net.HttpWebRequest       request;
    System.Net.HttpWebResponse      response;
    System.Byte[]                   byteArray;
    System.IO.Stream                dataStream;
    System.IO.StreamReader          streamRead;
    System.IO.StreamWriter          streamWrite;
    System.Net.ServicePoint         servicePoint;
    System.Net.ServicePointManager  servicePointmgr;
    System.Net.HttpVersion          version;
    System.Web.Script.Serialization.JavaScriptSerializer jsonSerializer;
    CLRObject                       clrObj;
    Newtonsoft.Json.JsonReader      reader;
    Newtonsoft.Json.Linq.JObject    prod;

    System.Text.Encoding            utf8;
    System.Exception                ex;
    Counter                         countCounter;
    Object                          obj;
    Map                             data;
    EcoResProduct                   ecoresproductfetch;
    EcoResProductTranslation        ecoresproductTranslation;
    InventTableModule               inventTableModule;




    try
    {
        InventTable     inventtable = sender as InventTable;

        System.Net.WebHeaderCollection  headers = new System.Net.WebHeaderCollection();
        var jsonSerializerobj = new  System.Web.Script.Serialization.JavaScriptSerializer();
        prod = new Newtonsoft.Json.Linq.JObject();
        inventOnHandQtyval = InventOnhand::newItemId(inventtable.ItemId).availPhysical();
        select inventTableModule where inventTableModule.ItemId==inventtable.ItemId;
        prod.Add("name",inventtable.itemName());
        prod.Add("productnumber",inventtable.ItemId);
        prod.Add("defaultuomscheduleid@odata.bind","/uomschedules(7F6F7338-1D80-4E90-9110-A70897C73834)");
        prod.Add("defaultuomid@odata.bind","/uoms(68A2E342-E1CA-4CC2-B430-C05057BCE7BC)");
        prod.Add("currentcost",0.00);
        prod.Add("description",inventtable.itemName());
        prod.Add("msdyn_fieldserviceproducttype",690970000);


        json=Newtonsoft.Json.JsonConvert::SerializeObject(prod);

        System.IO.MemoryStream mem = new System.IO.MemoryStream();



        new InteropPermission(InteropKind::ClrInterop).assert();



        headers = new System.Net.WebHeaderCollection();

        url = "https://abc.crm4.dynamics.com/api/data/v8.1/details";

        clrObj = System.Net.WebRequest::Create(url);

        aosUri = "https://login.windows.net/abcd1234/oauth2/authorize?";

        activeDirectoryTenant = "https://login.microsoftonline.com/abcd134/oauth2/token";

        activeDirectoryClientAppId = "xyz124";



        activeDirectoryResource = "https://abc.crm4.dynamics.com";

        Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authenticationContext =
                                new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(activeDirectoryTenant);



        var userCredential = new  Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential("abc@xyz.onmicrosoft.com", "abc@1234");

        Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult authenticationResult =
            authenticationContext.AcquireTokenAsync(activeDirectoryResource, activeDirectoryClientAppId, userCredential).Result;


        headers.Add("Authorization", authenticationResult.CreateAuthorizationHeader());

        headers.Add("Prefer", "return=representation");
        request = clrObj;

        request.Headers=headers;

        utf8 = System.Text.Encoding::get_UTF8();
        byteArray = utf8.GetBytes(json);
        request.set_Method("POST");
        request.set_KeepAlive(true);

        request.ContentType="application/json";

        request.set_ContentLength(byteArray.Length);







        servicePoint = request.get_ServicePoint();

        System.Net.ServicePointManager::set_Expect100Continue(false);

        System.Net.ServicePointManager::set_SecurityProtocol(System.Net.SecurityProtocolType::Tls12);



        dataStream = request.GetRequestStream();

        dataStream.Write(byteArray, 0, byteArray.get_Length());

        response = request.GetResponse();



            dataStream = response.GetResponseStream();


            streamRead = new System.IO.StreamReader(dataStream);

            jsonString = streamRead.ReadToEnd();



            data=RetailCommonWebAPI::getMapFromJsonString(jsonString);

            prdGUIDCode = data.lookup("productid");

            prodnum = data.lookup("productnumber");           

    }

    catch(Exception::CLRError)
    {
        ex = CLRInterop::getLastException().GetBaseException();
        error(ex.get_Message());
    }





    dataStream.Close();

    response.Close();

答案 1 :(得分:0)

我相信这种方法不起作用,问题是D365 Operations OData端点需要使用客户端密钥进行身份验证。在此方法中,在对服务的调用中作为承载令牌传递的JWT令牌未使用客户端密钥进行签名。我不认为有任何安全的方法可以从单个Web应用程序执行此操作。我要关闭它,因为我相信答案是创建第二个web api应用程序来处理呼叫,服务器端,并将数据传递回我的SPA

答案 2 :(得分:0)

这看起来像一个简单的拼写错误:

//Set Bearer token
req.setRequestHeader("Authorization", "Bearer " + token);

注意" Bearer"

之后的空格