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

JS通过XMLHttpRequest调用authorize授权URL报CORS错误咨询

CORS报错原因
  • 微软身份平台的/oauth2/v2.0/authorize是交互型授权端点,设计初衷就是供浏览器跳转加载登录页使用,服务端默认不会返回Access-Control-Allow-Origin响应头,只要你用XMLHttpRequest、fetch这类异步API发起跨域请求,就必然触发CORS拦截,和你修改navigator.userAgent的操作没有任何关系——UA修改只是改了请求头标识,根本绕不开浏览器层面的同源安全策略。
  • 你的调用思路本身不符合OAuth2授权流程规范:这个端点不会直接返回可被脚本读取的JSON/文本响应,它的逻辑是校验用户状态后,要么返回登录页让用户输入凭据,要么302跳转到你预先配置的重定向地址,本身就不支持XHR方式调用。
纯JS可行实现方案

所有方案都不需要发异步请求,完全基于浏览器原生导航能力实现,不会触发CORS问题。

方案1:整页跳转(最稳定,推荐)

直接将当前页面地址重定向到授权地址即可,用户完成登录后会自动跳回你配置的回调页,你在回调页解析地址栏携带的授权参数即可。
注意你原来的授权链接缺少两个必填参数,补全后才能正常使用:

  • response_type:授权流程类型,走授权码流填code,走隐式流填id_token
  • redirect_uri:登录完成后的跳转地址,必须和你在Azure AD应用后台配置的重定向URI完全一致,需要做URL编码

示例代码:

// 补全必填参数,redirect_uri记得替换成你自己的回调地址并编码
const authorizeUrl = new URL("https://login.microsoftonline.com/XXX-YYY-ZZZ-111-X1Z1/oauth2/v2.0/authorize")
authorizeUrl.searchParams.set('client_id', 'test')
authorizeUrl.searchParams.set('scope', 'openid')
authorizeUrl.searchParams.set('response_type', 'code')
authorizeUrl.searchParams.set('redirect_uri', 'http://localhost:8081/callback')
authorizeUrl.searchParams.set('sso_reload', 'true')

// 直接跳转,无CORS问题
window.location.href = authorizeUrl.toString()

跳转完成后,在http://localhost:8081/callback页面用如下代码解析授权码:

const urlParams = new URLSearchParams(window.location.search)
const authCode = urlParams.get('code')
if (authCode) {
  // 后续拿authCode换token、对接keycloak逻辑写在这里
}

方案2:弹窗授权(不打断当前页面操作)

如果不想离开当前业务页,可以用弹窗加载授权页,轮询监听弹窗地址变化,等弹窗跳回你的域名后,从弹窗地址中提取授权参数再关闭弹窗即可。
示例代码:

function triggerAuth() {
  // 先拼好和上面一样的授权地址
  const authorizeUrl = new URL("https://login.microsoftonline.com/XXX-YYY-ZZZ-111-X1Z1/oauth2/v2.0/authorize")
  authorizeUrl.searchParams.set('client_id', 'test')
  authorizeUrl.searchParams.set('scope', 'openid')
  authorizeUrl.searchParams.set('response_type', 'code')
  authorizeUrl.searchParams.set('redirect_uri', 'http://localhost:8081/callback')
  authorizeUrl.searchParams.set('sso_reload', 'true')

  // 打开弹窗
  const authWindow = window.open(authorizeUrl.toString(), 'msAuth', 'width=600,height=700,top=100,left=100')
  
  // 轮询监听弹窗地址
  const checkTimer = setInterval(() => {
    try {
      // 当弹窗跳回同域名地址时,即可正常访问location对象
      if (authWindow.location.origin === window.location.origin) {
        clearInterval(checkTimer)
        const params = new URLSearchParams(authWindow.location.search)
        const authCode = params.get('code')
        authWindow.close()
        // 拿到authCode走后续逻辑
        console.log('授权成功,授权码:', authCode)
      }
    } catch (err) {
      // 弹窗还在微软域名下时,跨域访问location会抛错,属于正常情况,忽略即可
      if (authWindow.closed) {
        clearInterval(checkTimer)
        console.log('用户关闭了登录弹窗')
      }
    }
  }, 400)
}

// 绑定到按钮点击等用户触发事件上即可调用,注意不要自动触发,不然会被浏览器拦截弹窗
document.getElementById('loginBtn').addEventListener('click', triggerAuth)

注意:不要尝试用本地代理、修改浏览器安全设置这类方式强行让XHR请求能拿到授权端点响应,这类操作要么违反浏览器安全规则,要么不符合OAuth2交互流程的设计,生产环境完全不可用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:09:28