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

使用Groovy连接MSGraph API时遇AADSTS900144错误求助

错误原因分析与解决方法

错误原因

  1. 端点误用:/oauth2/v2.0/authorize是OAuth2授权码流程的用户授权入口,用于引导用户登录并授权,和你之前使用的/token端点(用于获取/刷新令牌)属于完全不同的流程环节,两者的请求方式、参数传递规则完全不一致。
  2. 请求方式与参数传递错误:/authorize端点仅接受GET请求,所有参数必须放在URL的查询字符串中,不支持POST+JSON请求体的传递方式。你代码里不仅用了POST请求,还把参数写在JSON结构里,甚至注释掉了请求体的设置逻辑,导致client_id根本没有被传递到服务端,直接触发了AADSTS900144错误。
  3. 额外逻辑错误:授权码流程中client_secret不能在/authorize步骤传递,这个密钥应该在后续用授权码交换access token时,传给/token端点;另外你自定义的HMAC签名逻辑不符合Azure AD的OAuth2规范,完全没有必要添加。

解决方法

根据你的实际需求选择对应的方案:

场景1:原本需要实现客户端凭证流(无用户交互,服务间调用)

这是你最初使用/token端点的正确场景,改回原端点并调整参数格式即可:

import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import org.apache.http.entity.ContentType

// 配置凭证
def clientId = 'CLIENT_ID'
def clientSecret = 'CLIENT_SECRET'
def tenantId = 'TENANT-ID'

// 改回token端点
def url = "https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token"
// 客户端凭证流要求参数使用x-www-form-urlencoded格式
def body = "client_id=${clientId}&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=${clientSecret}&grant_type=client_credentials"

CloseableHttpClient httpclient = HttpClients.createDefault()
HttpPost httpPost = new HttpPost(url)
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded")
httpPost.setEntity(new StringEntity(body, ContentType.APPLICATION_FORM_URLENCODED))

def response = httpclient.execute(httpPost)
def responseBody = EntityUtils.toString(response.getEntity())
def code = response.getStatusLine().getStatusCode()

println 'Status: ' + code
println 'Body: ' + responseBody

httpclient.close()

场景2:确实需要实现授权码流(需要用户登录交互)

这种场景下必须用GET请求访问/authorize端点,参数直接拼在URL中,且不能传递client_secret:

import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils

def clientId = 'CLIENT_ID'
def tenantId = 'TENANT-ID'
def redirectUri = 'YOUR_REDIRECT_URI' // 必须是Azure AD应用中已配置的重定向URI

// 授权码流的authorize端点,参数直接拼在URL查询字符串中
def url = "https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize?client_id=${clientId}&response_type=code&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&redirect_uri=${redirectUri}"

CloseableHttpClient httpclient = HttpClients.createDefault()
HttpGet httpGet = new HttpGet(url)

def response = httpclient.execute(httpGet)
def responseBody = EntityUtils.toString(response.getEntity())
def code = response.getStatusLine().getStatusCode()

println 'Status: ' + code
println 'Body: ' + responseBody // 这里会返回登录页面HTML,实际场景需要引导用户访问该URL完成授权

httpclient.close()

注意:授权码流是完整的两步流程:

  1. 引导用户访问上述URL,用户登录授权后,Azure AD会跳转到你配置的redirectUri并携带code参数
  2. 拿着这个code调用/token端点,传递client_id、client_secret、code、redirect_uri、grant_type=authorization_code来获取access token

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:05:24