如何在Node.js后端脚本中获取Microsoft Graph API访问令牌?
解决非Web Node.js脚本调用Microsoft Graph API的认证问题
当然有合适的方法!对于非Web场景下的Node.js后端脚本,你完全可以摆脱回调URL的限制,用**客户端凭据流(Client Credentials Flow)**来完成认证——这种方式专门针对服务端后台任务设计,不需要用户交互,也不需要任何Web相关的回调配置。
核心思路
客户端凭据流是一种服务到服务的认证方式,你的Node.js脚本会以“应用身份”直接向Azure AD请求访问令牌,而不是以某个用户的身份。这意味着你需要先在Azure AD中注册一个应用程序,配置好权限,然后用应用的身份信息来获取令牌。
步骤1:在Azure AD中配置应用程序
- 登录Azure门户,进入Azure Active Directory → 应用注册,点击“新注册”。
- 选择“单租户”(适合内部后台脚本),名称随便填,不需要配置重定向URI(因为不需要回调)。
- 注册完成后,记录下客户端ID和租户ID(在“概述”页面)。
- 添加客户端凭据:进入“证书和密码” → “新客户端密码”,设置过期时间后保存,一定要把生成的密码复制下来(之后看不到了)。
- 配置Microsoft Graph权限:进入“API权限” → “添加权限” → 选择“Microsoft Graph” → 选择“应用权限”(注意不是“委派权限”),比如你需要读取用户就选
User.Read.All,需要管理组就选Group.ReadWrite.All等。 - 最后点击“授予管理员同意”(必须由租户管理员操作,否则脚本会提示权限不足)。
步骤2:用Node.js实现认证与API调用
推荐使用微软官方的@azure/msal-node(处理认证)和@microsoft/microsoft-graph-client(简化Graph API调用)库,先安装依赖:
npm install @azure/msal-node @microsoft/microsoft-graph-client @azure/identity
示例代码(使用Graph SDK)
require('dotenv').config(); // 推荐用dotenv管理环境变量,避免硬编码敏感信息 const { Client } = require('@microsoft/microsoft-graph-client'); const { TokenCredentialAuthenticationProvider } = require('@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials'); const { ClientCredentialCredential } = require('@azure/identity'); // 从环境变量读取配置(也可以直接写,但不推荐) const config = { tenantId: process.env.AZURE_TENANT_ID, clientId: process.env.AZURE_CLIENT_ID, clientSecret: process.env.AZURE_CLIENT_SECRET, scopes: ['https://graph.microsoft.com/.default'] // .default表示使用应用注册时配置的所有应用权限 }; // 创建凭据实例 const credential = new ClientCredentialCredential( config.tenantId, config.clientId, config.clientSecret ); // 初始化Graph客户端 const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: config.scopes }); const graphClient = Client.initWithMiddleware({ authProvider }); // 调用Graph API示例:获取租户内所有用户 async function fetchUsers() { try { const users = await graphClient.api('/users').select('displayName,mail').get(); console.log('获取到的用户列表:'); users.value.forEach(user => { console.log(`姓名:${user.displayName},邮箱:${user.mail}`); }); } catch (error) { console.error('调用Graph API失败:', error.message); } } // 执行 fetchUsers();
如果你想手动获取令牌并调用API(不使用Graph SDK)
也可以用@azure/msal-node直接获取令牌,然后用fetch或其他HTTP库调用:
require('dotenv').config(); const { ConfidentialClientApplication } = require('@azure/msal-node'); const msalConfig = { auth: { clientId: process.env.AZURE_CLIENT_ID, authority: `https://login.microsoftonline.com/${process.env.AZURE_TENANT_ID}`, clientSecret: process.env.AZURE_CLIENT_SECRET } }; const cca = new ConfidentialClientApplication(msalConfig); // 获取访问令牌 async function getAccessToken() { const result = await cca.acquireTokenByClientCredential({ scopes: ['https://graph.microsoft.com/.default'] }); return result.accessToken; } // 调用Graph API async function callGraphAPI() { const token = await getAccessToken(); const response = await fetch('https://graph.microsoft.com/v1.0/users', { headers: { 'Authorization': `Bearer ${token}` } }); if (!response.ok) { throw new Error(`API请求失败,状态码:${response.status}`); } const data = await response.json(); console.log('用户数据:', data.value); } callGraphAPI();
关键注意事项
- 权限配置:一定要选择“应用权限”而非“委派权限”,后者需要用户参与认证,不适合后台脚本。
- 管理员同意:应用权限必须经过租户管理员同意才能生效,否则会返回
Insufficient privileges to complete the operation错误。 - 敏感信息管理:绝对不要把客户端密码、租户ID等敏感信息硬编码在代码里,推荐用环境变量或者Azure Key Vault来管理。
- 令牌有效期:客户端凭据流获取的令牌有效期一般是1小时,过期后需要重新获取,
@azure/msal-node会自动处理令牌缓存和刷新。
内容的提问来源于stack exchange,提问作者Abarnett
相关产品推荐
相关产品推荐

