我正在尝试创建一个单页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,即使设置稍有不同。
答案 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"
之后的空格