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

如何使用PowerShell向Token添加Claims及AADSTS901001报错解决

问题

我有一个横向API,需通过包含Token验证策略的APIM供不同业务应用调用,因此需要生成Token以测试该APIM。但我在向Token中添加Claims时遇到问题,以下是我的尝试代码:

$tenantId = "****" 
$clientId = "****" 
$secret = "****" 
$scope = "https://graph.microsoft.com/.default"
$claims = @{
    "access_token" = @{
        "role" = "arole"
    }
} | ConvertTo-Json -Compress

$tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$body =  @{
    grant_type    = "client_credentials"
    Scope         = $scope
    Client_Id     = $clientId
    Client_Secret = $secret
    claims        = $claims
}

$connection = Invoke-RestMethod -Method POST -Uri $tokenEndpoint -Body $body
$token = $connection.access_token 
 
$token

这段代码返回如下错误(移除Claims部分则可正常运行):

Invoke-RestMethod : {"error":"invalid_request","error_description":"AADSTS901001: Invalid request. The claims request parameter value 'System.Collections.Hashtable' is invalid. Trace ID: da35dc46-7e9f-4a0d-a318-2dd7dc456d00 Correlation
ID: ca7aecf2-ee32-4d38-80c7-cda0e9e07394 Timestamp: 2024-10-24 19:00:01Z","error_codes":[901001],"timestamp":"2024-10-24
19:00:01Z","trace_id":"da35dc46-7e9f-4a0d-a318-2dd7dc456d00","correlation_id":"ca7aecf2-ee32-4d38-80c7-cda0e9e07394"}
At line:20 char:15
+ ... onnection = Invoke-RestMethod -Method POST -Uri $tokenEndpoint -Body  ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

解决方法

问题原因

错误提示claims request parameter value 'System.Collections.Hashtable' is invalid,说明传递给Azure AD的claims参数未被正确解析为JSON字符串:

  1. 即便将claims对象转为JSON字符串,PowerShell处理哈希表格式的Body时,会错误识别包含特殊字符的JSON字符串类型,导致参数值被判定为Hashtable。
  2. Azure AD的token端点要求claims参数必须是URL编码后的JSON字符串,直接传递未编码的JSON会触发格式校验错误。

修正后的代码

$tenantId = "****" 
$clientId = "****" 
$secret = "****" 
$scope = "https://graph.microsoft.com/.default"

# 构造claims对象并转为压缩JSON字符串
$claimsJson = @{
    "access_token" = @{
        "role" = "arole"
    }
} | ConvertTo-Json -Compress

# 对JSON字符串进行URL编码
$encodedClaims = [System.Web.HttpUtility]::UrlEncode($claimsJson)

$tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"

# 手动构造x-www-form-urlencoded格式的Body字符串
$body = "grant_type=client_credentials&scope=$scope&client_id=$clientId&client_secret=$secret&claims=$encodedClaims"

$connection = Invoke-RestMethod -Method POST -Uri $tokenEndpoint -Body $body -ContentType "application/x-www-form-urlencoded"
$token = $connection.access_token 
 
$token

关键修改点

  • URL编码JSON字符串:用[System.Web.HttpUtility]::UrlEncode()处理JSON,避免特殊字符破坏表单格式。
  • 手动构造Body:放弃哈希表格式,直接拼接标准的application/x-www-form-urlencoded字符串,确保参数解析无误。
  • 显式指定ContentType:明确告知端点Body格式,避免PowerShell自动推断时出现偏差。

可选方案(保留哈希表格式)

若偏好使用哈希表构造Body,只需确保claims值为编码后的字符串:

$tenantId = "****" 
$clientId = "****" 
$secret = "****" 
$scope = "https://graph.microsoft.com/.default"

$claimsJson = @{
    "access_token" = @{
        "role" = "arole"
    }
} | ConvertTo-Json -Compress
$encodedClaims = [System.Web.HttpUtility]::UrlEncode($claimsJson)

$tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$body =  @{
    grant_type    = "client_credentials"
    Scope         = $scope
    Client_Id     = $clientId
    Client_Secret = $secret
    claims        = $encodedClaims
}

$connection = Invoke-RestMethod -Method POST -Uri $tokenEndpoint -Body $body -ContentType "application/x-www-form-urlencoded"
$token = $connection.access_token 
 
$token

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:17:03