如何合并Microsoft Azure双API请求?解决数据与头像加载冲突
解决Azure AD登录中数据库访问与头像获取的权限冲突
问题本质
你遇到的核心问题是Azure AD令牌的受众(aud声明)限制:
- 使用
${clientId}/.default时,令牌的受众是你的应用Client ID,仅拥有访问用户专属数据库的权限,无Microsoft Graph访问权限,因此无法获取用户头像; - 使用
https://graph.microsoft.com/.default时,令牌的受众是Graph API,仅能调用Graph接口获取头像,但无访问你的数据库的权限,导致应用加载失败。
单个Azure AD令牌只能对应一个目标资源(受众),因此不能用同一个令牌同时访问你的应用数据库和Graph API,必须分开处理。
方案一:获取双令牌(推荐)
通过一次授权申请所有必要权限,再利用刷新令牌分别获取针对应用数据库和Graph API的独立令牌。
代码修改步骤
- 更新授权请求的权限范围
同时申请应用默认权限和Graph的User.Read权限:
// 合并应用权限与Graph权限 const scope = `${clientId}/.default https://graph.microsoft.com/User.Read offline_access`;
- 保留原令牌请求逻辑(获取数据库访问令牌)
维持tokenRequestScope为${clientId}/.default,该令牌用于访问用户专属数据库:
const tokenRequestScope = `${clientId}/.default`;
- 新增Graph令牌获取函数
利用已获取的刷新令牌,请求针对Graph API的专用令牌:
async function requestGraphToken() { const refreshToken = localStorage.getItem('refresh_token'); if (!refreshToken) return null; const tokensRequestUrl = `${baseUrl}/token?`; const config = { headers: { 'Content-Type': 'application/x-www-form-urlencoded', } }; const body = { 'client_id': clientId, 'scope': 'https://graph.microsoft.com/User.Read', 'refresh_token': refreshToken, 'grant_type': 'refresh_token', }; try { const response = await axios.post(tokensRequestUrl, body, config); if (response.status === 200) { localStorage.setItem('graph_access_token', response.data.access_token); return response.data.access_token; } } catch (err) { console.error('Failed to get Graph token:', err); return null; } }
- 登录成功后自动获取Graph令牌
修改check_auth_code函数,在登录完成后触发Graph令牌请求:
async function check_auth_code(authCode, onSuccess, onError) { if (authCode) { try { const data = await requestTokens(authCode); if (data) { localStorage.setItem('access_token', data.access_token); localStorage.setItem('refresh_token', data.refresh_token); // 获取Graph专用令牌 await requestGraphToken(); console.log('Success login'); onSuccess(); } else { console.log('Error login'); onError(); } } catch (err) { console.error('Login error:', err); onError(); } } }
- 分场景使用令牌
- 访问用户数据库时,使用存储的
access_token; - 调用Graph API获取头像时,使用
graph_access_token。
方案二:增量授权(可选)
如果不想一次性申请所有权限,可以先完成数据库访问的登录流程,当需要获取头像时,触发增量授权请求Graph权限:
function requestGraphAuthCode() { const authCodeRequestUrl = `${baseUrl}/authorize?` + `client_id=${clientId}` + `&response_type=code` + `&redirect_uri=${redirectUri}` + `&response_mode=query` + `&scope=https://graph.microsoft.com/User.Read` + `&prompt=consent`; // 强制用户确认新权限 window.open(authCodeRequestUrl, "_self"); }
在回调页面中,用新的授权码获取Graph令牌,并存入独立存储位置。
必要配置检查
确保你的Azure AD应用已完成以下配置:
- 添加了针对用户数据库的自定义API权限或应用角色,并完成管理员同意;
- 添加了Microsoft Graph的
User.Read委派权限,并完成管理员同意; - 应用的重定向URI配置正确,包含开发和生产环境的地址。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

