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

Golang集成Azure AD OAuth2换取Token返回401 Unauthorized错误

Azure AD OAuth2 回调报401错误修复

问题现象

  • 已确认client id、client secret配置正确,回调地址设为http://localhost:8080/callback,Azure AD后台已启用公共客户端流
  • 运行main.go可正常加载登录页,输入邮箱密码完成身份认证后,跳转回调地址时报错:Handler error: token response was 401 Unauthorized

点击登录后的页面
发送的请求头

问题原因

手动构造令牌请求的代码存在多处错误,导致Azure AD令牌端点拒绝请求:

  1. 核心参数缺失:授权码流程换token必须携带回调请求返回的code参数、已配置的client_secret参数,代码中完全没有传递这两个字段
  2. 参数编码错误:手动对scope、redirect_uri做了URL编码,但url.Values.Encode()方法本身会自动执行URL编码,造成双重编码后参数值不符合要求
  3. 参数冗余/不匹配:硬编码state=12345,和授权阶段生成的state值不一致;额外传递了仅授权阶段需要的response_type、response_mode参数,令牌端点不需要这两个字段
  4. 端点配置风险:AuthURL中租户ID占位符首字母大写,TokenURL中占位符全小写,实际替换时如果大小写不一致会直接请求到错误的端点
  5. 重复造轮子:golang.org/x/oauth2已经封装了标准OAuth2流程的令牌交换逻辑,手动构造请求极易出现参数遗漏、格式错误问题

修复步骤

1. 修正OAuth2基础配置

统一租户ID写法,补充所需权限范围,建议使用v2.0版本端点兼容性更好:

config = &oauth2.Config{
    ClientID:     "<替换为实际client id>",
    ClientSecret: "<替换为实际client secret,公共客户端可留空>",
    RedirectURL:  redirectURI,
    Endpoint: oauth2.Endpoint{
        AuthURL:  "https://login.microsoftonline.com/<替换为实际租户ID,统一小写>/oauth2/v2.0/authorize",
        TokenURL: "https://login.microsoftonline.com/<替换为和上方完全一致的租户ID>/oauth2/v2.0/token",
    },
    Scopes: []string{"openid", "profile", "offline_access", "User.Read"},
}

2. 重写回调处理逻辑

删除手动构造HTTP请求换token的代码,直接调用oauth2库内置的Exchange方法,该方法会自动处理参数拼接、编码、请求发送全流程:

func CallbackHandler(w http.ResponseWriter, req *http.Request) error {
    session, _ := store.Get(req, "session")

    // 校验state防CSRF
    if req.FormValue("state") != SessionState(session) {
        return Error{http.StatusBadRequest, "invalid callback state"}
    }

    // 从回调参数中取授权码
    code := req.FormValue("code")
    if code == "" {
        return Error{http.StatusBadRequest, "missing authorization code"}
    }

    // 调用库方法交换令牌
    token, err := config.Exchange(req.Context(), code)
    if err != nil {
        return fmt.Errorf("token exchange failed: %v", err)
    }

    // 令牌存入session
    session.Values["token"] = token
    if err := session.Save(req, w); err != nil {
        return fmt.Errorf("error saving session: %v", err)
    }

    http.Redirect(w, req, "/", http.StatusFound)
    return nil
}

3. 核对Azure AD后台配置

  • 重定向URI类型选择Web,值精确为http://localhost:8080/callback,末尾不要加斜杠
  • 若使用公共客户端模式,确认后台已开启「将应用程序视为公共客户端」开关,同时配置中ClientSecret留空
  • 确认已为应用授予Microsoft Graph -> User.Read委托权限

验证

重新运行程序,完成登录后即可正常跳转回首页,调用Graph接口获取用户信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 00:01:37