从Azure Functions中调用Microsoft Graph API

时间:2017-05-16 19:31:46

标签: javascript node.js azure microsoft-graph azure-functions

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

  1. 从Azure门户
  2. 创建了一个新的Azure功能应用程序
  3. 打开了应用服务身份验证"设置并指示它使用AAD登录(管理模式为Express)。
  4. 将应用配置为具有委托权限,例如"登录并阅读用户个人资料"对于Microsoft Graph。
  5. 创建了一个新的JavaScript函数HttpTriggerJS1
  6. 将此功能的授权级别更改为" Anonymous" (否则默认情况下"功能"级别甚至不允许我运行该功能,总是返回401 Unauthorized)
  7. 安装了必要的节点模块(npm install request
  8. 实际功能:

    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();
        });
    };
    
  9. 在单独的浏览器窗口中测试此功能。我正确地签了AAD。

  10. 但是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"
        }
      }
    }"
    
  11. 我查看了req.headers['x-ms-token-aad-access-token']获得的令牌。它类似于" AQABAA ....",这似乎与我之前看到的常规access_token有所不同,开始于" eyJ ....&#34 ;

    这里有什么问题?在调用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();
            });
        });
    };
    

3 个答案:

答案 0 :(得分:3)

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

  1. 在功能应用的AAD配置中分配默认资源。
  2. 使用AAD on-behalf-of flow与您的ID令牌(x-ms-token-aad-id-token)交换MS Graph访问令牌。
  3. 不需要任何代码更改的最简单方法是执行#1。我在我的App Service Auth and the Azure AD Graph API博客文章(需要一些更新)中概述了该过程,但我将在此处为Microsoft Graph提供功能优化版本。

    您需要做的主要事情是:

    1. 确保您的AAD设置包含客户端密码(您已经拥有此密码)。
    2. 确保您的AAD设置具有访问Microsoft Graph的权限(您已经完成此操作)。
    3. Resource Explorer中打开您的功能应用(使用平台设置下的门户中的链接),导航到左侧面板上的 config / authsettings ,将"additionalLoginParams"null更改为["resource=https://graph.microsoft.com"],然后保存更改。
    4. 执行此操作并再次登录后,x-ms-token-aad-access-token请求标头将始终为您提供可与Microsoft Graph一起使用的访问令牌。

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

答案 1 :(得分:0)

标题应包含正确的访问令牌(此处有更多详细信息): https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-authentication

这是另一篇文章遇到同样的错误并可能有所帮助: How do I create an auth token with the new microsoft graph api?

一种可能的解决方法是使用服务主体身份验证流程,您可以在其中启用功能应用程序以通过AAD调用Graph API。

https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-overview#service-to-service-authentication

答案 2 :(得分:0)

Azure Functions现在支持Microsoft Graph的本机身份验证。文档位于https://docs.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"
}

然后,您可以代表发出请求的用户查询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/");
}

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