You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用应用身份验证的Azure Functions(Node.js)调用Microsoft Graph遇阻

解决Azure Functions调用Microsoft Graph API的两个核心问题

我来帮你拆解你遇到的两个问题:HTTP 404绑定失效和访问令牌受众错误,这俩问题是不同原因导致的,咱们一步步捋清楚解决。

一、先搞定最关键的:"Access token validation failure. Invalid audience." 错误

你这里踩了一个很常见的坑:你用的是ID令牌(x-ms-token-aad-id-token)去调用Graph API,但Graph需要的是专门针对它的访问令牌。

为什么会报错?

  • x-ms-token-aad-id-token是ID令牌,它的受众(aud字段)是你的Azure Functions应用注册的客户端ID,作用是验证用户身份,根本不能直接用来调用Graph API。
  • Graph API要求访问令牌的受众必须是https://graph.microsoft.com,用ID令牌凑数肯定会触发受众验证失败。

正确姿势:用On-Behalf-Of(OBO)流程换取Graph访问令牌

因为你的Function是代表当前登录用户调用Graph,所以得用用户的ID令牌去换Graph的访问令牌,具体步骤如下:

  1. 配置AAD应用注册

    • 给你的Function App对应的AAD应用注册添加Graph的委托权限(比如User.Read),记得要授予管理员同意。
    • 记下应用的客户端ID、客户端密钥和租户ID,后面代码要用到。
  2. 修改Function代码实现OBO流程
    先装依赖:

    npm install @azure/msal-node @microsoft/microsoft-graph-client @microsoft/microsoft-graph-client/authProviders/azureTokenCredentials
    

    替换你的函数代码:

    const { ConfidentialClientApplication } = require('@azure/msal-node');
    const graph = require('@microsoft/microsoft-graph-client');
    const { TokenCredentialAuthenticationProvider } = require('@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials');
    
    module.exports = async function (context, req) {
        // 获取用户的ID令牌
        const idToken = req.headers['x-ms-token-aad-id-token'];
        if (!idToken) {
            context.res = { status: 400, body: '缺少用户身份令牌' };
            return;
        }
    
        // 配置MSAL,替换成你的应用信息
        const msalConfig = {
            auth: {
                clientId: '你的Function App客户端ID',
                clientSecret: '你的Function App客户端密钥',
                authority: 'https://login.microsoftonline.com/你的租户ID'
            }
        };
    
        const cca = new ConfidentialClientApplication(msalConfig);
    
        try {
            // 执行OBO流程,拿到Graph访问令牌
            const oboRequest = {
                oboAssertion: idToken,
                scopes: ['https://graph.microsoft.com/User.Read'], // 按需加需要的Graph权限
                skipCache: true
            };
    
            const tokenResponse = await cca.acquireTokenOnBehalfOf(oboRequest);
            const graphAccessToken = tokenResponse.accessToken;
    
            // 初始化Graph客户端
            const client = graph.Client.init({
                authProvider: new TokenCredentialAuthenticationProvider({
                    getToken: async () => ({ 
                        token: graphAccessToken, 
                        expiresOnTimestamp: Date.now() + 3600 * 1000 
                    })
                })
            });
    
            // 调用Graph API
            const user = await client.api('/me').get();
            context.log('获取用户信息成功:', user);
            context.res = { status: 200, body: user };
        } catch (error) {
            context.log.error('调用Graph API失败:', error);
            context.res = { 
                status: 500, 
                body: `错误详情: ${error.message || JSON.stringify(error)}` 
            };
        }
    };
    

二、解决HTTP 404绑定失效问题

这个问题大概率和路由配置或身份验证后的重定向有关,你可以按下面的步骤排查:

  • 检查函数路由配置:打开函数的function.json,确认route属性是否正确(没设置的话默认是api/函数名),部署后的路由和本地调试的路由要一致。
  • 验证身份验证配置:在Azure门户的Function App身份验证设置里,确保:
    • 没开启"允许匿名请求"
    • AAD身份提供者的客户端ID、租户ID和你应用注册的信息完全匹配
  • 浏览器调用方式:开了AAD身份验证后,直接在浏览器访问函数URL,会自动跳转到AAD登录页,登录成功后应该能正常访问;要是还是404,检查函数是不是部署错了(比如漏了文件,或者部署日志有报错)。
  • 手动调用注意事项:手动测试的时候,要把x-ms-token-aad-id-token放在请求头里,别放到Authentication: Bearer xxx里,因为Functions的身份验证中间件是靠x-ms-token-aad-id-token识别用户令牌的。

最后再提醒几个关键点

  • 一定要确保Function App的应用注册已经拿到了Graph权限的管理员同意,不然OBO流程会直接失败。
  • 别把客户端密钥硬写在代码里,建议用Azure Functions的应用设置(环境变量)存,比如process.env.CLIENT_SECRET。

内容的提问来源于stack exchange,提问作者monsty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:56:25