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

如何让基于Azure AD B2C认证的Web App通过Microsoft Graph访问M365环境

实现方案:Azure AD B2C用户与M365环境的权限化交互

核心思路

Azure AD B2C无法直接认证到M365,因此通过后端代理应用作为中间层,区分内部Azure AD用户和B2C本地用户的身份,分别采用不同的授权方式调用Microsoft Graph,实现权限隔离。

1. 标记用户身份类型

在Azure AD B2C的用户流(或自定义策略)中添加自定义声明,明确用户身份:

  • 对通过内部Azure AD租户登录的用户,提取租户ID判断归属,添加userType声明为internal
  • 对B2C本地账户用户,直接设置userType声明为external
  • 在Node.js/Express应用中,解析ID Token获取userType字段,作为权限判断依据

2. 配置Graph代理应用(内部Azure AD租户中)

在内部Azure AD租户下注册GraphProxyApp,用于统一调用Microsoft Graph:

  • 外部用户(B2C本地账户):
    • 为应用添加应用权限(如Sites.ReadWrite.All),并通过权限范围限制,仅允许操作指定M365列表/库
    • 启用客户端凭据流,让MyWebAppAPI可通过应用密钥获取Graph访问令牌
  • 内部用户(Azure AD账户):
    • 为应用添加委托权限(如Files.ReadWrite.All、Sites.ReadWrite.All),允许用户以自身身份调用Graph
    • 启用授权码流,支持MyWebApp代表用户获取Graph访问令牌

3. 后端权限控制实现(Node.js/Express)

在MyWebAppAPI中添加权限拦截逻辑,根据用户类型处理Graph调用:

外部用户处理逻辑

使用客户端凭据流获取Graph令牌,仅允许提交数据到指定资源:

const { ClientCredentialCredential } = require("@azure/identity");
const { Client } = require("@microsoft/microsoft-graph-client");
const { TokenCredentialAuthenticationProvider } = require("@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials");

async function getExternalGraphClient() {
  const credential = new ClientCredentialCredential(
    process.env.INTERNAL_TENANT_ID,
    process.env.GRAPH_PROXY_CLIENT_ID,
    process.env.GRAPH_PROXY_CLIENT_SECRET
  );
  const authProvider = new TokenCredentialAuthenticationProvider(credential, {
    scopes: ["https://graph.microsoft.com/.default"]
  });
  return Client.initWithMiddleware({ authProvider });
}

// 示例:提交表单数据到指定M365列表
async function submitFormToList(formData, siteId, listId) {
  const client = await getExternalGraphClient();
  return client.api(`/sites/${siteId}/lists/${listId}/items`)
    .post({ fields: formData });
}

内部用户处理逻辑

使用授权码流获取用户级别的Graph令牌,开放全权限读写:

const { AuthorizationCodeCredential } = require("@azure/identity");
const { Client } = require("@microsoft/microsoft-graph-client");
const { TokenCredentialAuthenticationProvider } = require("@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials");

async function getInternalGraphClient(authCode, redirectUri) {
  const credential = new AuthorizationCodeCredential(
    process.env.INTERNAL_TENANT_ID,
    process.env.GRAPH_PROXY_CLIENT_ID,
    process.env.GRAPH_PROXY_CLIENT_SECRET,
    authCode,
    redirectUri
  );
  const authProvider = new TokenCredentialAuthenticationProvider(credential, {
    scopes: ["https://graph.microsoft.com/Files.ReadWrite.All"]
  });
  return Client.initWithMiddleware({ authProvider });
}

// 示例:读取用户OneDrive文件
async function getUserOneDriveFiles(authCode, redirectUri) {
  const client = await getInternalGraphClient(authCode, redirectUri);
  return client.api("/me/drive/root/children").get();
}

4. 权限细化与安全加固

  • 外部用户的应用权限需限定到具体M365站点/列表,避免过度授权;可在Graph调用中直接指定资源ID,或通过Azure AD条件访问限制
  • 内部用户的委托权限通过Azure AD组或条件访问策略,限制仅特定用户/IP范围可获取高权限令牌
  • 对所有Graph操作添加审计日志,记录操作人ID、操作内容和时间
  • 定期轮换应用密钥,确保凭据安全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:15:52