如何用NodeJS获取Microsoft Teams Shifts班次?解决403权限错误
问题描述
我想用NodeJS获取Microsoft Teams中Shifts应用的班次列表,仅需获取名为“Main Shift”的特定排班。已在Azure AD注册名为microsoft-teams-shifts的应用并配置对应Microsoft Graph API权限,按官方文档实现认证逻辑后,调用https://graph.microsoft.com/v1.0/teams/{teamID}/schedule接口时持续收到403禁止错误,提示缺少Schedule.Read.All或Schedule.ReadWrite.All权限。相同请求在Graph Explorer中可正常执行,对比NodeJS生成的访问令牌与Graph Explorer的令牌,发现wids数组存在差异,寻求问题原因及解决办法。
相关代码
认证代码(auth.js)
// auth.js const msal = require('@azure/msal-node'); // Taken from: // portal.azure.com -> AD -> App Registrations -> 'microsoft-teams-shifts' -> Application (client ID) const CLIENT_ID = 'xxxx'; // Taken from: // 'microsoft-teams-shifts' -> Certificates & secrets -> 'microsoft-teams-shifts-secret' (the actual secret value, not the ID of it) const CLIENT_SECRET = 'xxxx'; // Taken from: // portal.azure.com -> AD -> App Registrations -> 'microsoft-teams-shifts' -> Directory (tenant) ID const TENANT_ID = 'xxxxx'; const config = { auth: { clientId: CLIENT_ID, clientSecret: CLIENT_SECRET, authority: `https://login.microsoftonline.com/${TENANT_ID}`, }, }; const cca = new msal.ConfidentialClientApplication(config); // Function to acquire a token async function getToken() { const tokenRequest = { scopes: ['https://graph.microsoft.com/.default'], // Include the required scope(s) here }; try { const authResult = await cca.acquireTokenByClientCredential(tokenRequest); return authResult.accessToken; } catch (error) { console.log(error); } } module.exports = getToken;
API请求代码
const axios = require('axios'); const getToken = require('./auth'); // Import the getToken function from auth.js async function fetchData() { try { const accessToken = await getToken(); // Call the getToken function to get the access token // Make the API call with Axios and pass the access token and required request headers // The Team ID is my Microsoft Teams 'team' ID const response = await axios.get('https://graph.microsoft.com/v1.0/teams/myTeamIDHere/schedule', { headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json', 'roles': 'Schedule.Read.All', // Include the required role permission }, }); // Process the response const data = response.data; console.log(data); } catch (error) { console.log(error.response.data.error); } } fetchData();
错误信息
{ "error": { "code": "Forbidden", "message": "Missing role permissions on the request. API requires one of 'Schedule.Read.All, Schedule.ReadWrite.All'. Roles on the request ''.", "innerError": { "date": "2023-04-14T08:00:04", "request-id": "xxxx", "client-request-id": "xxxx" } } }
问题原因及解决办法
核心问题分析
- 手动添加
roles请求头无效:Graph API不会读取请求头中的roles字段,权限信息完全依赖于access token内部的声明,你添加的这个字段属于多余操作,不会被识别。 - 应用权限未正确生效:虽然配置了权限,但应用权限需要租户管理员同意,且权限授予后可能存在延迟,或者你添加的是委派权限而非应用权限(客户端凭证流仅支持应用权限)。
- 令牌未包含所需权限:NodeJS生成的access token中
roles声明缺失目标权限,导致API判定无权限访问。
具体解决步骤
1. 移除无效的roles请求头
修改API请求代码,删除headers中的'roles': 'Schedule.Read.All'字段,修改后的代码如下:
const axios = require('axios'); const getToken = require('./auth'); async function fetchData() { try { const accessToken = await getToken(); const response = await axios.get('https://graph.microsoft.com/v1.0/teams/myTeamIDHere/schedule', { headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, }); console.log(response.data); } catch (error) { console.log(error.response.data.error); } } fetchData();
2. 确认应用权限已获得管理员同意
- 登录Azure AD门户,进入
microsoft-teams-shifts应用注册页面 - 切换到API权限选项卡,检查是否添加了应用类型的
Schedule.Read.All或Schedule.ReadWrite.All权限,且状态显示为「已授予[租户名]管理员同意」 - 若未授予同意,点击「授予管理员同意」按钮,完成后等待5-10分钟让权限生效
3. 验证令牌权限
- 重启NodeJS应用,重新获取access token
- 使用jwt.ms解码令牌,查看
roles数组中是否包含Schedule.Read.All或Schedule.ReadWrite.All - 若令牌中仍无对应权限,检查权限类型是否正确(必须是应用权限,而非委派权限,客户端凭证流不支持委派权限)
内容的提问来源于stack exchange,提问作者nopassport1
相关产品推荐
相关产品推荐

