一直在用这种方法将我的头撞在墙上,所以希望一些CRM/Dynamics专家能帮到我!
我正在尝试使用Node Powered Express应用程序中的一组管理员凭据以编程方式从我们的Dynamics CRM实例中获取数据。此Express应用程序托管在托管CRM的网络外部的单独服务器上。然后,该应用程序将向所有有权访问(由应用程序中的角色/权限控制)的登录用户请求,处理和提供CRM数据,这意味着最终用户仅需登录Express应用程序,而不必也登录通过ADFS,以便应用访问CRM实例。
我们的CRM设置是配置为面向Internet(IFD)的本地服务器。这将使用Active Directory联合身份验证服务。我们有在网络外围运行联合服务的Web应用程序代理服务器,这些服务器与内部网络上的ADFS服务器进行通信。 ADFS根据本地AD对从网络外部(从Internet)进行连接的用户进行身份验证。一旦通过身份验证,代理将允许用户连接到CRM。
由于具有混合部署,因此本地 Activity 目录与Azure AD同步。任何O365服务(在线交换,共享点等)都在后台使用Azure AD。我们同步Active Directory,因此我们只需要在一个地方管理用户。
CRM具有端点,例如端点。 https://my.crm.endpoint
,我已经在Azure门户中注册了一个应用程序(称为CRM App),其主页设置为CRM终结点https://my.crm.endpoint
。
问题是否将应用程序的主页设置为https://my.crm.endpoint
足以将其“链接”到我们的内部CRM实例?
我已经编写了一个脚本(crm.js),该脚本使用其App ID成功请求了在Azure Portal中注册的 CRM应用程序的访问 token 。
示例 token
eyJ0dWNyIjoiMSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzE5ZTk1...
然后,使用不记名 token ,尝试通过通常的终结点从Dynamics中获取一些联系人:https://my.crm.endpoint/api/data/v8.2/contacts?$select=fullname,contactid
这失败,并且我收到
401 Unauthorised
错误消息。问题谁能建议这个问题是什么?和/或提供有关如何挂接Web应用程序(在我的情况下为Express)的详细信息,以向运行在使用ADFS的本地服务器(IFD)上的Dynamics CRM发出经过身份验证的请求?
crm.js
let util = require('util');
let request = require("request");
let test = {
username: '<[email protected]>',
password: '<my_password>',
app_id: '<app_id>',
secret: '<secret>',
authenticate_url: 'https://login.microsoftonline.com/<tenant_id>/oauth2/token',
crm_url: 'https://<my.crm.endpoint>'
};
function CRM() { }
CRM.prototype.authenticate = function () {
return new Promise((resolve, reject) => {
let options = {
method: 'POST',
url: test.authenticate_url,
formData: {
grant_type: 'client_credentials',
client_id: test.app_id, // application id
client_secret: test.secret, // secret
username: test.username, // on premise windows login (admin)
password: test.password, // password
resource: test.app_id // application id
}
};
// ALWAYS RETURNS AN ACCESS_TOKEN
request(options, function (error, response, body) {
console.log('AUTHENTICATE RESPONSE', body);
resolve(body);
});
})
};
CRM.prototype.getContacts = function (token) {
return new Promise((resolve, reject) => {
let options = {
method: 'GET',
url: `${test.crm_url}/api/data/v8.2/contacts?$select=fullname,contactid`,
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
'OData-MaxVersion': 4.0,
'OData-Version': 4.0,
'Content-Type': 'application/json; charset=utf-8'
}
};
request(options, (error, response, body) => {
console.log('getContacts', util.inspect(error), util.inspect(body));
resolve(body);
});
});
};
let API = new CRM(); // instantiate the CRM object
API.authenticate() // call authenticate function
.then(response => {
if (response) {
let json = JSON.parse(response);
let token = json.access_token;
console.log('TOKEN', token);
API.getContacts('token')
.then(contacts => {
// DO SOMETHING WITH THE CONTACTS
console.log('CONTACTS', contacts);
})
}
});
module.exports = CRM;
错误响应
HTTP Error 401 - Unauthorized: Access is denied
其他信息
我当前的解决方案基于这些文档...
https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service
更新
遵循@ andresm53的评论,我认为我确实需要直接针对ADFS进行身份验证。我发现this blog post描述了可在OFS中使用的ADFS中生成共享 secret 。
“使用这种形式的客户端身份验证,您可以将客户端标识符(作为client_id)和客户端 secret (作为client_secret)发布到STS端点。这是这样的HTTP POST(使用“客户端证书授予”,仅添加了换行符)的示例以提高可读性):”
resource=https%3a%2f%2fmy.crm.endpoint
&client_id=**2954b462-a5de-5af6-83bc-497cc20bddde ** ???????
&client_secret=56V0RnQ1COwhf4YbN9VSkECTKW9sOHsgIuTl1FV9
&grant_type=client_credentials
更新2
现在,我已经在ADFS中创建了服务器应用程序,并且正在使用正确的client_id和client_secret发布上述有效负载。
但是,我收到了
Object moved
消息。RESOLVED BODY: '<html><head><title>Object moved</title></head><body>\r\n<h2>Object moved to <a href="https://fs.our.domain.name/adfs/ls/?wa=wsignin1.0&wtrealm=https%3a%2f%2fmy.crm.endpoint%2f&wctx=http%253a%252f%252f2954b462-a5de-5af6-83bc-497cc20bddde%252f&wct=2018-04-16T13%3a17%3a29Z&wauth=urn%3afederation%3aauthentication%3awindows">here</a>.</h2>\r\n</body></html>\r\n'
问题谁能描述我在做错什么以及我应该做些什么,以便针对ADFS/CRM正确进行身份验证?
注意:当我在浏览器中访问
https://my.crm.endpoint
时,系统会提示我输入我的用户名和密码。输入我的信誉,我就可以使用CRM。在“网络”标签中是否注意到它正在使用NTLM来执行此操作?这会改变我需要采取的方法吗?更新3
请查看新问题here
最佳答案
我们也有这种情况。
我们的组织是OnPrem 8.2。可通过VPN或家庭网络进行访问。
如果您以非常普通的外行方式看待问题,那么我们的CRM便无法从外部获得。
我们所做的是
请不要将此与Dynamics CRM OOB WebAPI混淆。我的意思是创建我们自己的API并将其作为服务使用自己的用户名和密码添加到IIS中。
我认为这至少会给您一些提示,让您了解应该朝哪个方向发展。
关于node.js - 如何从Web应用程序查询本地Dynamics CRM( Node/快捷方式),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49763453/