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

React中使用Azure B2C调用Graph SDK获取用户信息遇令牌验证错误

问题分析与解决方案

问题1:自定义Scope导致受众无效

你用的https://my-tanent.onmicrosoft.com/my-app/user.read是针对自身应用的API权限Scope,不是Microsoft Graph的官方Scope。用这个Scope获取的令牌,受众(aud)是你的客户端ID,而Graph API要求令牌的aud必须是https://graph.microsoft.com,自然会触发“无效受众”的错误。

问题2:使用.defaultScope返回空令牌

https://graph.microsoft.com/.default是一种静态Scope,需要满足两个前提:

  1. 你的B2C应用已正确添加Microsoft Graph的委派权限(比如User.Read);
  2. 已对该权限授予管理员同意(B2C租户的管理员同意需要用全局管理员账号操作)。
    另外,登录请求(loginRequest)中必须包含Graph相关的Scope,否则MSAL不会缓存对应的访问令牌,导致acquireTokenSilent无法获取到令牌,返回空值。

修正步骤

  1. 确认权限配置

    • 登录Azure门户,找到你的B2C应用,进入「API权限」页面;
    • 添加Microsoft Graph的委派权限(比如User.Read);
    • 点击「授予管理员同意」,完成权限授权。
  2. 修正代码中的Scope
    调用Graph API必须使用Microsoft Graph的官方Scope,可直接简写为User.Read(MSAL会自动补全前缀https://graph.microsoft.com/),同时确保登录请求中也包含该Scope。

  3. 修正后的完整代码

import React from 'react';
import {
  AuthenticatedTemplate,
  UnauthenticatedTemplate,
  useMsal,
} from '@azure/msal-react';
import { loginRequest } from '../authConfig';
import { InteractionRequiredAuthError } from '@azure/msal-browser';
import { AuthCodeMSALBrowserAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/authCodeMsalBrowser';
import { InteractionType } from '@azure/msal-browser';
import { Client } from '@microsoft/microsoft-graph-client';

const Home = () => {
  const { instance } = useMsal();
  const { accounts } = useMsal();
  let graphClient = undefined;

  // 使用Microsoft Graph的官方Scope
  const scopes = [
    'openid',
    'offline_access',
    'User.Read'
  ];

  const authProvider = new AuthCodeMSALBrowserAuthenticationProvider(instance, {
    account: accounts[0],
    scopes,
    interactionType: InteractionType.Popup,
  });

  function ensureClient() {
    graphClient = Client.initWithMiddleware({
      authProvider: authProvider,
    });
    return graphClient;
  }

  async function getUser() {
    try {
      ensureClient();
      const user = await graphClient
        .api('/me')
        .select('displayName,mail,mailboxSettings,userPrincipalName')
        .get();
      console.log(user);
    } catch (error) {
      console.error('获取用户信息失败:', error);
    }
  }

  const getAccessToken = async () => {
    try {
      // 明确指定账户,避免多账户场景下的问题
      const token = await instance.acquireTokenSilent({
        scopes,
        account: accounts[0]
      });
      console.log('获取到的令牌:', token);
    } catch (error) {
      // 静默获取失败时,弹出窗口请求令牌
      if (error instanceof InteractionRequiredAuthError) {
        const token = await instance.acquireTokenPopup({ scopes });
        console.log('弹窗获取到的令牌:', token);
      } else {
        console.error('获取令牌失败:', error);
      }
    }
  };

  return (
    <>
      <UnauthenticatedTemplate>
        <h3 className="h3">Login</h3>
        <button onClick={() => instance.loginPopup(loginRequest)}>Login</button>
      </UnauthenticatedTemplate>

      <AuthenticatedTemplate>
        <div className="App">
          <header className="App-header">
            <p>Hello {accounts[0]?.name}!</p>
            <button onClick={() => instance.logoutRedirect({ postLogoutRedirectUri: '/' })}>Logout</button>
            <button onClick={() => getUser()}>Get User</button>
            <button onClick={() => getAccessToken()}>AcquireTokenSilent</button>
          </header>
        </div>
      </AuthenticatedTemplate>
    </>
  );
};
  1. 修正authConfig中的loginRequest
    确保登录请求包含Graph的Scope:
// authConfig.js
export const loginRequest = {
  scopes: ['openid', 'offline_access', 'User.Read']
};

额外注意事项

  • 验证令牌的aud字段是否为https://graph.microsoft.com,只有这样的令牌才能被Graph API接受;
  • 如果仍出现空令牌问题,清除浏览器缓存后重新登录,确保MSAL缓存了正确的访问令牌。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 23:03:23