使用Groovy连接MSGraph API时遇AADSTS900144错误求助
错误原因分析与解决方法
错误原因
- 端点误用:
/oauth2/v2.0/authorize是OAuth2授权码流程的用户授权入口,用于引导用户登录并授权,和你之前使用的/token端点(用于获取/刷新令牌)属于完全不同的流程环节,两者的请求方式、参数传递规则完全不一致。 - 请求方式与参数传递错误:
/authorize端点仅接受GET请求,所有参数必须放在URL的查询字符串中,不支持POST+JSON请求体的传递方式。你代码里不仅用了POST请求,还把参数写在JSON结构里,甚至注释掉了请求体的设置逻辑,导致client_id根本没有被传递到服务端,直接触发了AADSTS900144错误。 - 额外逻辑错误:授权码流程中
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()
注意:授权码流是完整的两步流程:
- 引导用户访问上述URL,用户登录授权后,Azure AD会跳转到你配置的
redirectUri并携带code参数- 拿着这个
code调用/token端点,传递client_id、client_secret、code、redirect_uri、grant_type=authorization_code来获取access token
内容的提问来源于stack exchange,提问作者ceebs75a
相关产品推荐
相关产品推荐

