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

无法获取Azure服务主体访问令牌:CORS与400错误求助

问题描述

我尝试在React前端通过以下代码获取服务主体的访问令牌:

const response = await fetch('https://login.microsoftonline.com/{tenent-id}/oauth2/token', {
      method: "POST",
      mode: "cors",
      cache: "no-cache",
      credentials: "same-origin",
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      redirect: "follow",
      referrerPolicy: "origin",
      body: new URLSearchParams({
        "client_id": '',
        "grant_type": 'client_credentials',
        "client_secret": '',
        "resource": ''
      }),
    }).then(async (res) => { console.log('res:', await res.json()); })

执行时触发CORS错误:

Access to fetch at 'https://login.microsoftonline.com/xx/oauth2/token' from origin 'http://localhost:3000' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

我把mode改成"no-cors"后,出现400错误且响应为空,但禁用Chrome CORS或用Postman请求时能正常运行。另外我使用两个不同的服务主体:一个用于MSAL(可正常工作),另一个用于访问公司内部API(即当前出问题的这个)。

想请教:有没有办法让浏览器单独忽略该请求的CORS且不出现400错误?或者有其他安全的服务主体令牌获取方式?


解决方案

1. 浏览器无法单独绕过单请求CORS限制

浏览器的CORS是全局安全策略,没有官方途径让单个请求跳过CORS检查。本地开发时用Chrome启动参数关闭CORS只是临时调试手段,不能用于生产环境。设置no-cors后,浏览器会完全屏蔽响应内容,同时请求的参数、头信息会被限制,导致请求格式失效,这就是你遇到400错误的原因。

2. 推荐方案:后端中转请求(安全且合规)

服务主体的client_secret是敏感凭证,绝对不能暴露在前端代码中,一旦泄露会导致租户权限被滥用。正确的做法是通过后端做中转:

  • 在你的后端(如Node.js、Java、Python等)编写一个接口,由后端发起令牌请求到微软登录服务器
  • 前端调用自己的后端接口获取令牌,再用令牌访问内部API
  • 后端可以安全存储client_id和client_secret,且后端请求不受浏览器CORS限制

3. 临时测试方案:用MSAL.js调用客户端凭证流(不推荐生产用)

如果只是临时测试需要在前端处理,可以尝试用MSAL.js的客户端凭证流,但此方式会暴露client_secret,存在极大安全风险:

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

const pca = new PublicClientApplication({
  auth: {
    clientId: "你的客户端ID",
    authority: "https://login.microsoftonline.com/你的租户ID"
  }
});

const tokenRequest = {
  scopes: ["https://你的内部API域名/.default"],
  clientSecret: "你的客户端密钥"
};

pca.acquireTokenByClientCredential(tokenRequest)
  .then(response => {
    console.log("获取到的令牌:", response.accessToken);
  })
  .catch(error => {
    console.error("获取令牌失败:", error);
  });

注意:仅用于本地临时测试,生产环境必须改用后端中转方案。

4. 替代思路:切换到用户上下文令牌

如果你的内部API支持,可以考虑使用MSAL获取的用户身份令牌(而非服务主体令牌)访问API,这样可以复用已有的MSAL认证流程,完全避开CORS问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:45:08