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

Office Add-In访问Dataverse Web API的最佳实践:免重复登录与密钥安全

最佳实践:Office Add-In 无重复登录访问 Dataverse Web API(无需 MS Graph/客户端密钥)

核心方案:Office.js SSO 能力 + Azure AD 公共客户端应用注册

完全符合你不想存储客户端密钥的需求,利用 Outlook 已有登录会话实现无缝授权,无需额外跳转登录。

1. Azure AD 应用注册配置

  • 注册时选择**公共客户端(移动和桌面应用)**类型,这类应用无需客户端密钥,天然适配前端/Office Add-In 无法安全存储敏感信息的场景
  • 添加 API 权限:找到你的 Dataverse 环境对应的 API(格式为 https://<你的组织域名>.crm.dynamics.com),添加 user_impersonation 权限,建议由管理员批量授予租户级权限,避免用户逐个同意
  • 配置重定向 URI:选择「单页应用(SPA)」类型,添加本地开发 URI(如 https://localhost:3000)和生产环境的 Add-In 域名 URI,同时必须添加 Office SSO 专用回调 URI:https://<你的Add-In域名>/auth-callback.html

2. 用 Office.js 直接获取 Dataverse 访问令牌

无需额外第三方包,直接调用 Office.js 内置的 SSO 接口,复用 Outlook 已有的用户会话:

async function getDynamicsAccessToken() {
  try {
    const dataverseResource = "https://<你的组织域名>.crm.dynamics.com";
    // 请求Dataverse专属令牌,明确不涉及MS Graph
    const token = await Office.auth.getAccessToken({
      allowSignInPrompt: true, // 仅用户未登录时触发登录提示
      forMSGraphAccess: false,
      extraQueryParameters: `resource=${encodeURIComponent(dataverseResource)}`
    });
    return token;
  } catch (err) {
    console.error("令牌获取失败:", err);
    throw err;
  }
}

3. 调用 Dataverse Web API

拿到令牌后,在请求头中携带即可访问数据表:

async function fetchDataverseTable(tableLogicalName) {
  const token = await getDynamicsAccessToken();
  const apiUrl = `https://<你的组织域名>.crm.dynamics.com/api/data/v9.2/${tableLogicalName}`;
  
  const response = await fetch(apiUrl, {
    method: "GET",
    headers: {
      "Authorization": `Bearer ${token}`,
      "OData-MaxVersion": "4.0",
      "OData-Version": "4.0",
      "Accept": "application/json"
    }
  });

  if (!response.ok) {
    throw new Error(`API 请求失败: ${response.statusText}`);
  }
  
  return await response.json();
}

关键注意事项

  • 最小权限原则:仅申请 Dataverse 的 user_impersonation 权限,避免过度授权
  • 多环境适配:如果需要支持多个 Dataverse 环境,可让用户配置组织 URL,或通过 Office 上下文获取租户 ID 动态拼接资源 URI
  • 令牌过期处理:当 API 返回 401 错误时,重新调用 getAccessToken 获取新令牌即可

进阶方案:用 MSAL.js 实现更灵活的身份流程

如果需要刷新令牌等高级功能,可使用 @azure/msal-browser,但仍需配置为公共客户端模式,无需客户端密钥:

import { PublicClientApplication } from "@azure/msal-browser";

const msalConfig = {
  auth: {
    clientId: "<你的应用客户端ID>",
    authority: "https://login.microsoftonline.com/<你的租户ID>",
    redirectUri: "https://<你的Add-In域名>/auth-callback.html"
  }
};

const pca = new PublicClientApplication(msalConfig);

async function getTokenWithMSAL() {
  const resource = "https://<你的组织域名>.crm.dynamics.com";
  const request = { scopes: [`${resource}/user_impersonation`] };
  
  try {
    // 静默复用Outlook登录会话
    const resp = await pca.ssoSilent(request);
    return resp.accessToken;
  } catch (silentErr) {
    // 仅当静默失败时弹出登录窗口(极少触发,因为Outlook已有会话)
    const resp = await pca.loginPopup(request);
    return resp.accessToken;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 08:40:34