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

Office Script使用Fetch请求OAuth2 Token返回Failed to Fetch问题排查

Office Script 实现OAuth密码模式获取令牌失败的解决思路

问题背景

尝试用Office Script编写获取OAuth API令牌的函数,已有可正常运行的PowerShell示例,但使用fetch实现时返回“failed to fetch”错误。

可正常运行的PowerShell代码

#requires -Version 3.0
function New-ApiAccessToken
{
    param
    (
        [string]$apiUrl,
        [string]$apiKey,
        [string]$apiSecretKey
    )

    # Specify security protocols
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'

    # Convert password to secure string
    $securePassword = ConvertTo-SecureString -String 'public' -AsPlainText -Force

    # Define parameters for Invoke-WebRequest cmdlet
    $params = @{
        Credential  =   New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ('public-client', $securePassword)
        Uri         =   '{0}/auth/oauth/token' -f $apiUrl
        Method      =   'POST'
        ContentType =   'application/x-www-form-urlencoded'
        Body        =   'grant_type=password&username={0}&password={1}' -f $apiKey, $apiSecretKey
    }
    
    # Request access token
    try {(Invoke-WebRequest @params | ConvertFrom-Json).access_token}
    catch {$_.Exception}
}

# Define parameters
$params = @{
    apiUrl          =   'myurlhere'
    apiKey          =   'thekey'
    apiSecretKey    =   'thesecretkey'
}

# Call New-ApiAccessToken function using defined parameters 
New-ApiAccessToken @params

报错的Office Script代码

async function getToken() {
  let url = 'myurlhere';
  let client_id = 'public-client';
  let client_secret = 'public';
  let username = 'thekey';
  let password = 'thesecretkey';

  let basicAuth: string = base64Encode(client_id + ":" + client_secret).toString();
  let bodyParams: URLSearchParams = new URLSearchParams();
  bodyParams['grant_type'] = 'password';
  bodyParams['username'] = username;
  bodyParams['password'] = password;

  let response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Accept': 'application/json; charset=UTF-8',
      'Authorization': 'Basic ' + basicAuth
    },
    body: bodyParams
    });

  let token: string = await response.json();
  console.log(token)  
}

抓包对比结果

  • PowerShell脚本发起2次POST请求:第一次返回401,第二次获取令牌返回200
  • Office Script仅发起1次OPTIONS请求,返回401,无后续请求

解决方案

1. 修正请求URL

PowerShell中拼接了完整的令牌端点路径{0}/auth/oauth/token,但Office Script里的url仅写了基础地址myurlhere,缺少后续路径,导致请求地址错误,需补充完整路径。

2. 处理CORS预检OPTIONS 401问题

Office Script运行在浏览器环境,跨域请求会先发送OPTIONS预检请求。若API服务器未配置允许OPTIONS请求通过,会直接返回401,阻断后续POST请求。需联系API管理员配置CORS规则:

  • 允许Office Script的请求Origin(或临时设为*测试)
  • 允许Content-Type、Authorization等请求头
  • 允许POST方法
  • 配置OPTIONS请求跳过认证校验

3. 确保Basic Auth编码正确

Office Script中的自定义base64Encode可能存在实现问题,改用浏览器原生的btoa()函数完成Base64编码:

let basicAuth: string = btoa(`${client_id}:${client_secret}`);

注意:btoa仅支持ASCII字符,若包含特殊字符需先转码。

4. 调整请求体构造方式

直接用字符串拼接请求体,确保格式与PowerShell完全一致,避免URLSearchParams可能带来的格式差异:

let body = `grant_type=password&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`;

5. 完整修正后的Office Script代码

async function getToken() {
  let baseUrl = 'myurlhere';
  // 补充完整的令牌端点路径
  let url = `${baseUrl}/auth/oauth/token`;
  let client_id = 'public-client';
  let client_secret = 'public';
  let username = 'thekey';
  let password = 'thesecretkey';

  // 使用浏览器原生btoa进行Base64编码
  let basicAuth: string = btoa(`${client_id}:${client_secret}`);
  // 手动构造符合要求的请求体字符串
  let body = `grant_type=password&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`;

  try {
    let response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json; charset=UTF-8',
        'Authorization': `Basic ${basicAuth}`
      },
      body: body
    });

    if (!response.ok) {
      // 打印详细错误信息便于排查
      const errorText = await response.text();
      console.error(`请求失败,状态码:${response.status},响应内容:${errorText}`);
      return;
    }

    let tokenData = await response.json();
    console.log(`获取到的令牌:${tokenData.access_token}`);
    return tokenData.access_token;
  } catch (error) {
    console.error(`请求异常:${error}`);
  }
}

关键说明

跨域预检OPTIONS 401是核心问题,若无法修改API服务器的CORS配置,Office Script的跨域请求将无法完成。同时需确保请求地址、请求体格式、Basic Auth编码完全匹配PowerShell的成功请求,减少格式差异导致的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:55:18