从 Azure Functions 内部调用 Microsoft Graph API

Yut*_*ang 5 javascript azure node.js azure-functions microsoft-graph-api

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

  1. 从 Azure 门户创建了一个新的 Azure Function App
  2. 开启“应用服务认证”设置并指示其使用AAD登录(管理模式为Express)。
  3. 将应用配置为具有委派权限,例如 Microsoft Graph 的“登录并读取用户配置文件”。
  4. 创建了一个新的 JavaScript 函数 HttpTriggerJS1
  5. 将此函数的授权级别更改为“匿名”(否则默认情况下“函数”级别甚至不允许我运行该函数,总是返回 401 Unauthorized)
  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();
        });
    };
    
    Run Code Online (Sandbox Code Playgroud)
  8. 在单独的浏览器窗口中测试了此功能。让我正确登录 AAD。

  9. 但是从 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"
        }
      }
    }"
    
    Run Code Online (Sandbox Code Playgroud)

我查看了我从req.headers['x-ms-token-aad-access-token']. 它类似于“AQABAA....”,这似乎与我之前看到的以“eyJ....”开头的常规 access_token 不同。

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

谢谢!

编辑:

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

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();
        });
    });
};
Run Code Online (Sandbox Code Playgroud)

Chr*_*lum 5

使用 Azure 应用服务身份验证/授权时,有两种方法可以使此工作正常进行:

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

不需要任何代码更改的最简单方法是执行#1。我在我的应用服务身份验证和 Azure AD Graph API博客文章(需要一些更新)中概述了该过程,但我会在此处为您提供 Microsoft Graph 的函数优化版本。

您需要做的主要事情是:

  1. 确保您的 AAD 设置包含客户端机密(您已经拥有此机密)。
  2. 确保您的 AAD 设置具有访问 Microsoft Graph 的权限(您已经这样做了)。
  3. Resource Explorer 中打开函数应用(使用门户中的Platform Settings下的链接),导航到左侧面板上的config/authsettings"additionalLoginParams"从更改null["resource=https://graph.microsoft.com"],然后保存更改。

执行此操作并再次登录后,x-ms-token-aad-access-token请求标头将始终为您提供适用于 Microsoft Graph 的访问令牌。

上述方法的缺点是,如果您需要从函数应用访问多个受 AAD 保护的资源,它对您没有帮助。如果这对您来说是个问题,那么您需要使用上面的方法#2。


Ale*_*lex 5

Azure Functions 现在支持 Microsoft Graph 的本机身份验证。文档位于https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-microsoft-graph

还有一个视频https://azure.microsoft.com/en-us/resources/videos/azure-friday-navigating-the-microsoft-graph-with-azure-functions-henderson/

例如,您可以创建一个 HttpTrigger 函数并将以下内容添加到 function.json。

{
   "type": "token",
   "direction": "in",
   "name": "graphToken",
   "resource": "https://graph.microsoft.com",
   "identity": "userFromRequest"
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以代表发出请求的用户查询 Graph API。访问令牌作为参数传入,您可以将其作为标头添加到 HttpClient

using System.Net; 
using System.Net.Http; 
using System.Net.Http.Headers; 

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, string graphToken, TraceWriter log)
{
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken);
    return await client.GetAsync("https://graph.microsoft.com/v1.0/me/");
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用 ClientCredentials 身份验证模式运行函数,这意味着它作为应用程序运行,而不是在特定用户的上下文中运行。