一尘不染

从Azure函数内部调用Microsoft Graph API

node.js

我正在尝试编写一个调用Microsoft Graph API的简单Azure函数。但是我无法使access_token工作。这是我所做的:

  1. 通过Azure门户创建了一个新的Azure Function应用
  2. 打开“ App Service Authentication”设置,并指示其使用AAD登录(管理模式为Express)。
  3. 将应用配置为具有Microsoft Graph的委派权限,例如“登录并读取用户个人资料”。
  4. 创建了一个新的JavaScript函数HttpTriggerJS1
  5. 将此功能的授权级别更改为“匿名”(否则默认情况下,“功能”级别甚至不允许我运行该功能,始终返回401未经授权)
  6. 安装了必要的Node模块(npm install request
  7. 和实际功能:
        var request = require('request');
    module.exports = function (context, req) {
        var token = req.headers['x-ms-token-aad-access-token'];
        var reqUrl = 'https://graph.microsoft.com/v1.0/me/';
        request.get(reqUrl, {'auth': {'bearer': token}}, function (err, response, msg) {
            context.res = {
                body: msg
            };
            context.done();
        });
    };
  1. 在单独的浏览器窗口中测试了此功能。正确登录AAD。

  2. 但是从Graph返回的消息是:

        "{
      "error": {
        "code": "InvalidAuthenticationToken",
        "message": "CompactToken parsing failed with error code: -2147184105",
        "innerError": {
          "request-id": "4c78551d-f0fe-4104-b1d3-e2d96fd3c02c",
          "date": "2017-05-16T19:11:14"
        }
      }
    }"

我调查了从中获得的令牌req.headers['x-ms-token-aad-access-token']。类似于“ AQABAA
....”,它似乎与我之前见过的以“ eyJ ....”开头的常规access_token不同。

这有什么问题吗?调用Graph API时,是否应该使用请求标头中的access_token?

谢谢!

编辑:

根据克里斯·吉伦(Chris
Gillum)的建议,我还研究了“代收”流程。这是我更新的函数,它通过提供id_token(从请求标头中检索)来获取特定资源(在我的情况下为https://graph.microsoft.com)的access_token

    var request = require('request');

    module.exports = function (context, req) {
        var parameters = {
            grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
            client_id: process.env.WEBSITE_AUTH_CLIENT_ID,
            client_secret: process.env.WEBSITE_AUTH_CLIENT_SECRET,
            assertion: req.headers['x-ms-token-aad-id-token'],
            resource: 'https://graph.microsoft.com',
            requested_token_use: 'on_behalf_of'
        };
        request.post('https://login.microsoftonline.com/microsoft.com/oauth2/token', {form: parameters}, function (aadErr, aadResponse, aadMsg) {
            var msgJson = JSON.parse(aadMsg);
            request.get('https://graph.microsoft.com/v1.0/me/', {'auth': {'bearer': msgJson.access_token}}, function (err, response, msg) {
                context.res = {
                    body: msg
                };
                context.done();
            });
        });
    };

阅读 408

收藏
2020-07-07

共1个答案

一尘不染

使用Azure App Service身份验证/授权时,有两种方法可以使此项工作:

  1. 在功能应用程序的AAD配置中分配默认资源。
  2. 使用AAD 代表流程将您的ID令牌(x-ms-token-aad-id-token)交换为MS Graph访问令牌。

不需要任何代码更改的最简单方法是执行#1。我在我的App Service Auth和Azure AD Graph
API
博客文章(需要一些更新)中概述了该过程,但是在这里我将为您提供Microsoft Graph的经过功能优化的版本。

您需要做的主要事情是:

  1. 确保您的AAD设置包括一个客户机密(您已经有此密码)。
  2. 确保您的AAD设置具有访问Microsoft Graph的权限(您已经完成了此操作)。
  3. 资源浏览器中打开函数应用程序(使用门户网站中 平台设置 下的链接),导航至左侧面板上的 config / authsettings"additionalLoginParams"从更改null["resource=https://graph.microsoft.com"],然后保存更改。

完成此操作并再次登录后,x-ms-token-aad-access-token请求标头将始终为您提供与Microsoft Graph一起使用的访问令牌。

上述方法的缺点是,如果您需要从功能应用程序访问多个受AAD保护的资源,那么它无济于事。如果这对您来说是个问题,那么您将需要使用上面的方法2。

2020-07-07