Динамика Бизнес Центральное Azure AD ADAL Несанкционированный - PullRequest
0 голосов
/ 13 октября 2018

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

Сравнил токены аутентификации, выданные для Postman и в NodeJ, используя 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"
  }

1 Ответ

0 голосов
/ 14 октября 2018

Некоторые службы имеют строгий строгий при проверке значения 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 от имени вошедшего в систему пользователя, я предлагаю посмотреть passport-azure-ad.
  2. Особенно, если вы планируете иметь общесистемную учетную запись или токен доступа, будьте очень осторожно возвращая исходный ответ конечному пользователю.Это верно даже при разработке, поскольку при переходе на работу очень легко пропустить нечто подобное и раскрыть то, что может быть очень привилегированным токеном доступа для неавторизованного пользователя.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...