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

Outlook插件应用无法获取SSO Token问题求助

问题背景

按照微软Office SSO开发文档实现后端获取SSO Token,具体实现如下:

前端代码(获取Access Token并传递给后端)

OfficeRuntime.auth
  .getAccessToken({ allowConsentPrompt: true, allowSignInPrompt: true, forMSGraphAccess: true })
  .then((token) => {
    console.log(token);
    axios
      .get(process.env.REACT_APP_FUNC_ENDPOINT + URLS.GET_GRAPH_DATA, {
        headers: { Authorization: "Bearer " + token },
      })
      .then((data) => {
        console.log(data);
        event.completed();
      });
  });

后端代码(通过On-Behalf-Of流程兑换Graph Token)

export async function getAccessToken(authorization: string): Promise<any> {
  if (!authorization) {
    let error = new Error("No Authorization header was found.");
    return Promise.reject(error);
  } else {
    const scopeName: string = process.env.SCOPE || "User.Read";
    const [, /* schema */ assertion] = authorization.split(" ");

    const tokenScopes = (jwt.decode(assertion) as jwt.JwtPayload).scp.split(
      " "
    );
    const accessAsUserScope = tokenScopes.find(
      (scope) => scope === "access_as_user"
    );
    if (!accessAsUserScope) {
      throw new Error("Missing access_as_user");
    }

    const formParams = {
      client_id: process.env.CLIENT_ID,
      client_secret: process.env.CLIENT_SECRET,
      grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
      assertion: assertion,
      requested_token_use: "on_behalf_of",
      scope: [scopeName].join(" "),
    };

    const stsDomain: string = "https://login.microsoftonline.com";
    const tenant: string = "common";
    const tokenURLSegment: string = "oauth2/v2.0/token";
    const encodedForm = form(formParams);
    let tokenResponse;
    try {
      tokenResponse = await axios.post(
        `${stsDomain}/${tenant}/${tokenURLSegment}`,
        encodedForm,
        {
          headers: {
            Accept: "application/json",
            "Content-Type": "application/x-www-form-urlencoded",
          },
        }
      );
    } catch (error) {
      console.log(error);
    }

    return tokenResponse.data;
  }
}

遇到的问题

  1. 触发错误:

'AADSTS65001: The user or administrator has not consented to use the application with ID '64f01276-0XXX' named 'ssoaddins'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 9a6a62f0-e698-48f3-ac77-ca18c0bbbd00\r\nCorrelation ID: 58843565-b171-4165-ab24-face78a43dfb\r\nTimestamp: 2023-03-15 01:23:42Z'

前端已设置allowConsentPrompt: true,但未弹出用户授权界面,且已在Azure中配置无需管理员审批的委托权限。

  1. 调整代码后获取的Graph Token无效。

问题解答

一、allowConsentPrompt: true未弹出授权界面且触发AADSTS65001错误的场景

以下几种情况会导致该问题:

  • 前后端权限范围不匹配:前端调用getAccessToken时仅设置forMSGraphAccess: true,未明确指定scopes参数,默认仅请求access_as_user权限,未包含后端需要的User.Read等Graph权限。此时后端用On-Behalf-Of流程请求未被前端预授权的权限,无法触发前端授权弹窗。
  • 租户权限策略限制:即使Azure配置了无需管理员审批的权限,若租户管理员设置「禁止用户自行同意应用权限」策略,会直接拦截授权弹窗,导致无法完成同意流程。
  • Office客户端环境限制:
    • 桌面版Office中,系统弹窗拦截器可能阻止授权窗口弹出;
    • 浏览器版Office运行在iframe中,部分浏览器的跨域安全策略会限制弹窗显示。
  • 应用注册权限未生效:虽然配置了权限,但权限处于「已请求」状态而非「已授予」——用户从未手动同意过该应用权限,或管理员未批量授予,即使权限无需审批,也需要触发一次授权流程才能生效。
  • 前端流程提前终止:代码中event.completed()在授权或后端请求完成前调用,导致Office客户端提前结束任务,终止授权弹窗流程。

二、Graph Token无效的解决方法

按以下步骤排查修复:

  1. 验证Token核心字段
    用JWT解码工具解析Token,检查:

    • aud字段是否为https://graph.microsoft.com(有效Graph Token的受众必须是该地址);
    • scp字段是否包含所需的Graph权限(如User.Read);
    • exp字段是否未过期。
  2. 检查后端On-Behalf-Of参数
    确保参数配置正确:

    • client_id和client_secret与Azure应用注册信息完全一致;
    • scope参数严格匹配需要的Graph权限(多个权限用空格分隔);
    • grant_type和requested_token_use分别为urn:ietf:params:oauth:grant-type:jwt-bearer和on_behalf_of;
    • STS请求地址https://login.microsoftonline.com/common/oauth2/v2.0/token正确(单租户应用需替换common为租户ID/域名)。
  3. 完善后端错误捕获
    修改后端catch块,返回详细错误信息,便于定位问题:

    catch (error) {
      const errMsg = error.response?.data || error.message;
      console.error("Token兑换失败:", errMsg);
      return Promise.reject(errMsg);
    }
    
  4. 确保前端传递的Token有效
    解码前端获取的Access Token,确认:

    • 包含access_as_user权限;
    • iss(签发者)和aud(受众)符合Office SSO要求(iss应为https://login.microsoftonline.com/{tenantId}/v2.0,aud应为应用注册的Client ID)。
  5. 调整前端权限请求
    在getAccessToken中明确指定后端需要的Graph权限,确保前端预授权:

    OfficeRuntime.auth
      .getAccessToken({ 
        allowConsentPrompt: true, 
        allowSignInPrompt: true, 
        forMSGraphAccess: true,
        scopes: ["User.Read"] // 匹配后端的scope配置
      })
      .then((token) => {
        // 后续逻辑
      });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 07:57:57