如何使用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字符串:
- 即便将claims对象转为JSON字符串,PowerShell处理哈希表格式的Body时,会错误识别包含特殊字符的JSON字符串类型,导致参数值被判定为Hashtable。
- 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
相关产品推荐
相关产品推荐

