【问题标题】:Dynamics Business Central Azure AD ADAL UnauthorizedDynamics Business Central Azure AD ADAL 未经授权
【发布时间】:2018-10-15 01:21:19
【问题描述】:

我开发了一个简单的 express 应用程序来测试在 NodeJS 中使用 Dynamics Business Central 和 ADAL 的身份验证。我收到以下 401 错误。身份验证在 Postman 中按预期工作,我可以在该上下文中调用 Dynamics REST 端点。在下面的 JavaScript 中,我在 Postman 中使用相同的 AAD 租户、客户端 ID 和客户端密码,但我无法进行身份验证。

比较 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"
  }

【问题讨论】:

    标签: node.js rest azure-active-directory adal dynamics-365


    【解决方案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,我建议查看 passport-azure-ad。
    2. 特别是如果您计划拥有系统范围的帐户或访问令牌,请非常小心地将原始响应返回给最终用户。即使在开发过程中也是如此,因为在转移到生产环境时很容易忽略类似的事情,并将可能是非常特权的访问令牌暴露给未经授权的用户。

    【讨论】:

    • 感谢 Philippe,我仍然收到 401 并删除了斜杠。将尝试您提到的 passport-azure-ad。
    • 404 还是 401? (您的原始帖子说 401。)
    • 对不起,是的 401 未经授权
    • 相关用户帐户是否已获得 Dynamics 365 Business Central 的授权? (例如,您可以登录门户吗)
    • 是的 grdegr@grdegr.onmicrosoft.com 用户,如果有影响,我正在使用 trail bc 实例
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多