Я стучал головой о несколько стен, так что некоторые эксперты CRM/Dynamics могут дать мне руку!
Я пытаюсь программно получить данные из нашего экземпляра Dynamics CRM, используя один набор учетных данных администратора в приложении Express для приложения с узлом. Это приложение Express размещено на отдельном сервере за пределами нашей сети, где размещается CRM. Приложение будет запрашивать, обрабатывать и обслуживать CRM-данные обратно любому зарегистрированному пользователю, который имеет доступ (контролируется ролями/разрешениями в приложении), что означает, что конечный пользователь должен войти в приложение Express, и не должен также войти в систему через ADFS, чтобы приложение могло получить доступ к экземпляру CRM.
Наш CRM настроен на локальном сервере, настроенном на интернет-выход (IFD). Это использует службы федерации Active Directory. У нас есть прокси-серверы веб-приложений, на которых запущены службы федерации по периметру сети, которые взаимодействуют с серверами ADFS во внутренней сети. ADFS проверяет подлинность пользователей, подключающихся извне сети (из Интернета) против предварительного AD. После аутентификации прокси позволяет пользователям подключаться к CRM.
Наш предварительный активный каталог синхронизируется с Azure AD, поскольку у нас есть гибридное развертывание. Любой сервис O365 (обмен онлайн, sharepoint и т.д.) Использует Azure AD в фоновом режиме. Мы синхронизируем Active Directory, поэтому нам нужно управлять пользователями только в одном месте.
CRM имеет конечную точку, например https://my.crm.endpoint
и я зарегистрировал приложение (называемое CRM-приложением) на Azure Portal, а домашняя страница установлена на конечную точку CRM https://my.crm.endpoint
.
Вопрос. Устанавливает ли домашняя страница приложения https://my.crm.endpoint
достаточно, чтобы "связать" ее с нашим экземпляром CRM на месте?
Я написал сценарий (crm.js), который успешно запрашивает токен доступа для моего приложения CRM, зарегистрированного на Azure Portal, используя его ID приложения.
Пример маркера
eyJ0dWNyIjoiMSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzE5ZTk1...
Используя токен-носитель, я затем пытаюсь получить некоторые контакты из Dynamics с помощью обычной конечной точки: https://my.crm.endpoint/api/data/v8.2/contacts? $ Select = fullname, contactid
Это не удается, и я получаю сообщение об ошибке 401 Unauthorised
.
Вопрос: Может ли кто-нибудь предложить проблему? И/или предоставить подробную информацию о том, как вы можете подключить веб-приложение (Express в моем случае), чтобы сделать аутентифицированные запросы к CRM Dynamics, работающим на локальном сервере (IFD), который использует ADFS?
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
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ
Мое текущее решение основано на этих документах...
ОБНОВИТЬ
Следуя комментарию @andresm53, я думаю, мне нужно пройти аутентификацию непосредственно с ADFS. Я нашел это сообщение в блоге, которое описывает создание общего секрета в ADFS, которое можно использовать с OAuth.
"Используя эту форму аутентификации клиента, вы бы поставили свой клиентский идентификатор (как client_id) и ваш клиентский секрет (как client_secret) на конечную точку STS. Вот пример такой HTTP-POST (с использованием Credentials Client Credentials, добавленных разрывов строк для удобства чтения): "
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="#" onclick="location.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'; return false;">here</a>.</h2>\r\n</body></html>\r\n'
ВОПРОС Кто-нибудь может описать, что я делаю неправильно, и что я должен делать, чтобы правильно аутентифицировать ADFS/CRM?
NB: Когда я нахожусь в своем браузере и посещаю https://my.crm.endpoint
, мне будет предложено ввести мое имя пользователя и пароль. Ввод моих кредитов работает, и я получаю доступ к CRM. Заметили на вкладке сети, что для этого используется NTLM? Означает ли это, какой подход мне нужно предпринять?
ОБНОВЛЕНИЕ 3
Пожалуйста, смотрите новый вопрос здесь