Dynamics Business Central Azure AD ADAL Неавторизовано

Я разработал простое экспресс-приложение для тестирования аутентификации с помощью Dynamics Business Central и ADAL в NodeJS. Я получаю следующую ошибку 401. Аутентификация в Postman работает должным образом, и в этом контексте я могу вызвать конечную точку Dynamics REST. В приведенном ниже JavaScript я использую тот же клиент AAD, идентификатор клиента и секрет клиента в Postman, но я не могу пройти аутентификацию.

Сравнил токены аутентификации, предоставленные в Postman и в NodeJs, используя https://jwt.io/, и единственная разница в том, что значения заголовка и uti в полезной нагрузке.

Когда я попадаю на свой getcompanies маршрут, я получаю следующую ошибку. Я перечислил версии пакетов моих узлов внизу сообщения.

Ошибка { error: { code: '401', message: 'Unauthorized' } }

Исходный код

var AuthenticationContext = require('adal-node').AuthenticationContext;
var crypto = require('crypto');
var express = require('express');
var request = require('request');

require('dotenv').config()
var clientId = process.env.CLIENT_ID;
var clientSecret = process.env.CLIENT_SECRET;

var authorityHostUrl = 'https://login.windows.net';
var azureAdTenant = 'grdegr.onmicrosoft.com';

var dynBusinessCentralCommonEndpoint = 'https://api.businesscentral.dynamics.com/v1.0/' + azureAdTenant + '/api/beta';

var bcRedirectUri = 'http://localhost:1337/getbctoken';

var dynBusinessCentralAuthUrl = authorityHostUrl + '/' +
                        azureAdTenant +
                        '/oauth2/authorize?response_type=code&client_id=' +
                        clientId +
                        '&redirect_uri=' +
                        bcRedirectUri +
                        '&state=<state>&resource=' +
                        'https://api.businesscentral.dynamics.com';

var app = express();
var port = 1337;
app.listen(port, () => console.log(`Example app listening on port ${port}!`))

app.get('/bcauth', function(req, res) {
  crypto.randomBytes(48, function(ex, buf) {
    var bcToken = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
    res.cookie('bcauthstate', bcToken);
    var dynBusinessCentralAuthUrlauthorizationUrl = dynBusinessCentralAuthUrl.replace('<state>', bcToken);

    console.log('redirecting to auth url: ' + dynBusinessCentralAuthUrlauthorizationUrl);
    res.redirect(dynBusinessCentralAuthUrlauthorizationUrl);
  });
});

var bcAccessToken = '';
app.get('/getbctoken', function(req, res) {

  var authorityUrl = authorityHostUrl + '/' + azureAdTenant;
  var authenticationContext = new AuthenticationContext(authorityUrl);

  console.log('getting bc auth context');
  authenticationContext.acquireTokenWithAuthorizationCode(
    req.query.code,
    bcRedirectUri,
    'https://api.businesscentral.dynamics.com/',
    clientId,
    clientSecret,
    function(err, response) {
      var message = '';
      if (err) {
        message = 'error: ' + err.message + '\n';
        return res.send(message)
      }

      bcAccessToken = response.accessToken;
      console.log('bc token\n' + bcAccessToken);

      res.send('bc access token updated');
    }
  );
});       

app.get('/getcompanies', (req, res) => {

  var body = '';
  var options = {
    url: 'https://api.businesscentral.dynamics.com/v1.0/grdegr.onmicrosoft.com/api/beta/companies',
    method: 'GET',
    headers: {
      Authorization: 'Bearer ' + bcAccessToken
    },
    json: JSON.stringify(body)
  };

  request(options, (err, response, body) => {
    res.send(response || err);

    if (response) {
      console.log(body);
    }
    else {
      console.log('response is null');
    }
  });
});

Пакеты узлов

"devDependencies": {
    "adal-node": "^0.1.28",
    "request": "^2.87.0",
    "webpack": "^4.12.0",
    "webpack-cli": "^3.0.8"
  },
  "dependencies": {
    "dotenv": "^6.1.0"
  }

person greg    schedule 12.10.2018    source источник


Ответы (1)


Некоторые службы очень строго проверяют значение aud (аудитория) токена доступа. Dynamics 365 Business Central ожидает, что аудитория маркеров доступа будет точно https://api.businesscentral.dynamics.com. В вашем коде вы запрашиваете и получаете токен доступа для https://api.businesscentral.dynamics.com/. Эта косая черта в конце - это то, что заставляет Dynamics 365 отклонять ваш токен доступа как недействительный.

Измените запрос токена на:

authenticationContext.acquireTokenWithAuthorizationCode(
  req.query.code,
  bcRedirectUri,
  'https://api.businesscentral.dynamics.com', // <-- No trailing slash!
  clientId,
  clientSecret,
  // ...

... и он должен работать.

Однако в вашем примере есть два важных момента:

  1. Шаблон, которому вы следуете, немного странный, хотя это может быть связано с тем, что вы находитесь на ранних этапах разработки, или потому, что это был просто минимальный пример воспроизведения для этого вопроса. Вам не следует не хранить токен доступа таким образом, потому что следующий человек, который вызовет /getcompanies, сможет сделать это, позвонив от имени пользователя, который первоначально вошел в систему, вместо того, чтобы войти в систему самостоятельно. Если вы хотите, чтобы пользователи входили в систему с помощью Azure AD и как часть этого, звоните в Dynamics 365 от имени вошедшего пользователя, я предлагаю посмотреть _ 6_.
  2. Особенно если вы планируете иметь общесистемную учетную запись или токен доступа, будьте очень осторожны, возвращая исходный ответ конечному пользователю. Это верно даже при разработке, поскольку очень легко упустить из виду что-то подобное при переходе к производству и раскрытии того, что может быть очень привилегированным токеном доступа неавторизованному пользователю.
person Philippe Signoret    schedule 14.10.2018
comment
Спасибо, Филипп, я все еще получаю 401 с удаленной косой чертой. попробую упомянутый вами паспорт-лазурное объявление. - person greg; 20.10.2018
comment
404 или 401? (В вашем исходном сообщении указано 401.) - person Philippe Signoret; 20.10.2018
comment
извините да 401 Unauthorized - person greg; 20.10.2018
comment
Авторизована ли соответствующая учетная запись пользователя для Dynamics 365 Business Central? (например, можете ли вы войти на портал) - person Philippe Signoret; 20.10.2018
comment
да, пользователь [email protected], я использую экземпляр trail bc, если это имеет значение - person greg; 20.10.2018
comment
Что, если вы удалите идентификатор клиента из конечной точки API? Согласно документации, конечная точка, которую вы должны использовать с аутентификацией Azure AD, - это https://api.businesscentral.dynamics.com/v1.0/api/beta (без имени домена клиента). docs.microsoft.com/en-us/dynamics- навигация / - person Philippe Signoret; 20.10.2018