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

如何解决C#调用Azure AD获取AccessToken时的AADSTS900144错误?

解决AADSTS900144错误:获取Azure AD访问令牌失败问题

错误详情

{
    "error": "invalid_request",
    "error_description": "AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: e605b59b-ce96-443a-be34-a80c00b84f00\r\nCorrelation ID: d6a891a8-4aed-485c-939d-95a377ca1c3d\r\nTimestamp: 2023-07-21 11:14:38Z",
    "error_codes": [
        900144
    ],
    "timestamp": "2023-07-21 11:14:38Z",
    "trace_id": "e605b59b-ce96-443a-be34-a80c00b84f00",
    "correlation_id": "d6a891a8-4aed-485c-939d-95a377ca1c3d",
    "error_uri": "https://login.microsoftonline.com/error?code=900144"
}

原问题代码

private static async Task<string> GetAccessTokenAsync(string tenantId, string azureClientId, string code, string azureRedirectURI, string azureResourceURI)
{
    using (var httpClient = new HttpClient())
    {
        var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";

        var requestBody = $"grant_type=authorization_code&client_id={azureClientId}&code={code}&redirect_uri={azureRedirectURI}&resource={azureResourceURI}";

        var content = new StringContent(requestBody, System.Text.Encoding.UTF8, "application/x-www-form-urlencoded");

        var response = await httpClient.PostAsync(tokenEndpoint, content);

        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            // Assuming the response contains a JSON string
            // You may want to use a JSON serializer to deserialize the responseContent.
            // For simplicity, we're assuming it's a JSON string.
            // You can use NewtonSoft.Json.JsonConvert.DeserializeObject to deserialize the JSON.
            return responseContent;
        }
        else
        {
            // Handle the error if needed
            // You can check response.StatusCode and response.ReasonPhrase for more details.
            throw new Exception($"Request failed with status code: {response.StatusCode}, Reason: {response.ReasonPhrase}");
        }
    }
}

问题分析

AADSTS900144错误提示请求体缺少grant_type参数,但代码中已明确拼接该参数,大概率是手动拼接请求体时的编码问题:如果参数(如授权码code)包含特殊字符(如&、=、+等),会破坏表单参数的结构,导致Azure AD服务器无法正确解析出grant_type参数。

另外,StringContent虽然指定了application/x-www-form-urlencoded类型,但不会自动对参数进行URL编码,这也是导致参数解析失败的常见原因。

代码修复方案

改用FormUrlEncodedContent构建请求体,它会自动处理参数的URL编码,避免手动拼接的错误:

private static async Task<string> GetAccessTokenAsync(string tenantId, string azureClientId, string code, string azureRedirectURI, string azureResourceURI)
{
    using (var httpClient = new HttpClient())
    {
        var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";

        // 使用字典组织参数,自动处理URL编码
        var formData = new Dictionary<string, string>
        {
            ["grant_type"] = "authorization_code",
            ["client_id"] = azureClientId,
            ["code"] = code,
            ["redirect_uri"] = azureRedirectURI,
            ["resource"] = azureResourceURI
        };

        var content = new FormUrlEncodedContent(formData);

        var response = await httpClient.PostAsync(tokenEndpoint, content);

        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            // 建议使用JSON序列化库(如Newtonsoft.Json或System.Text.Json)解析响应
            // 示例:var tokenResult = JsonConvert.DeserializeObject<TokenResponse>(responseContent);
            return responseContent;
        }
        else
        {
            // 捕获错误响应内容,便于排查问题
            var errorContent = await response.Content.ReadAsStringAsync();
            throw new Exception($"请求失败,状态码: {response.StatusCode},错误详情: {errorContent}");
        }
    }
}

// 可选:定义TokenResponse类用于解析响应
// public class TokenResponse
// {
//     [JsonProperty("access_token")]
//     public string AccessToken { get; set; }
//     [JsonProperty("token_type")]
//     public string TokenType { get; set; }
//     [JsonProperty("expires_in")]
//     public int ExpiresIn { get; set; }
// }

运行代码前的前置检查

  • 确认Azure AD应用注册的**客户端ID(azureClientId)和租户ID(tenantId)**完全正确,无拼写或格式错误
  • 验证**重定向URI(azureRedirectURI)**与应用注册中配置的重定向URI完全一致,包括协议(HTTP/HTTPS)、域名和路径
  • 确保授权码code有效:未过期(默认有效期10分钟)、与当前客户端ID和重定向URI匹配,且未被使用过(授权码仅可使用一次)
  • 确认**资源URI(azureResourceURI)**正确对应AVD服务,通常为https://rdweb.wvd.microsoft.com
  • 检查应用注册是否已配置AVD相关的API权限(如Windows Virtual Desktop的权限),必要时完成管理员同意
  • 确认令牌端点无误:授权码流程的端点为https://login.microsoftonline.com/{tenantId}/oauth2/token,确保租户ID替换正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:44:53