PowerShell调用Microsoft Graph返回400错误,求排查建议
问题描述
我用以下PowerShell脚本拉取近30天未登录的用户并导出为CSV文件,之前正常运行数月,近期突然失效,报错:Invoke-WebRequest: 远程服务器返回错误: (400) Bad Request。
脚本代码:
$ApplicationID = "Application ID placeholder" $TenatDomainName = "Tenant placeholder" $AccessSecret = "Access secret placeholder" $SignInDate = Get-Date -Date (Get-Date).Date.addDays(-30) -Format "yyyy-MM-dd"` $Body = @{ Grant_Type = "client_credentials" Scope = "https://graph.microsoft.com/.default" client_Id = $ApplicationID Client_Secret = $AccessSecret } $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenatDomainName/oauth2/v2.0/token" -Method POST -Body $Body $token = $ConnectGraph.access_token $Users = Invoke-MSCloudIdMSGraphQuery -AccessToken $Token -GraphQuery "beta/users?filter=signInActivity/lastSignInDateTime le $SignInDate" | Where-Object userPrincipalName -like '*@placeholder.uk' | Select displayName,userPrincipalName,onPremisesSamAccountName | Export-CSV C:\temp\AZusersinactive.csv
我已检查Azure应用注册中的证书和访问密钥,状态均正常,请问可能是哪里出现了变动?
可能的原因及排查方向
1. Graph API查询格式不规范
你的$SignInDate仅格式化到日期(yyyy-MM-dd),但Graph API要求lastSignInDateTime使用ISO 8601标准的日期时间格式(例如2024-05-20T00:00:00Z)。直接传入纯日期字符串会导致过滤语法错误,触发400请求。
修复方式:修改日期格式化代码:
$SignInDate = (Get-Date).Date.AddDays(-30).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
2. Beta版API发生变更
你调用的是Graph API的beta预览版本,微软会不定期调整预览版的接口语法、参数或权限规则。如果signInActivity字段的过滤逻辑被修改,就会导致请求失败。
排查方式:尝试切换到稳定的v1.0版本API(注意v1.0中signInActivity需要特定应用权限,部分场景可能无法返回数据):
$Users = Invoke-MSCloudIdMSGraphQuery -AccessToken $Token -GraphQuery "v1.0/users?filter=signInActivity/lastSignInDateTime le $SignInDate" | ...
3. 应用权限缺失或变更
虽然密钥状态正常,但应用的Graph API权限可能被意外移除,或者微软更新了signInActivity的权限要求。获取用户登录活动需要User.Read.All或AuditLog.Read.All的应用权限(非委派权限),且必须已授予管理员同意。
排查方式:在Azure应用注册的「API权限」中确认:
- 已添加Microsoft Graph的
User.Read.All(应用权限) - 权限状态显示「已授予管理员同意」
4. 租户安全策略限制
租户若开启了条件访问策略,可能限制了该应用对Graph API的访问;或者租户的Graph API访问被临时限流,也会触发400错误。
排查方式:
- 检查租户的「条件访问」策略,确认未阻止该应用的Graph API访问
- 查看Azure AD的「审核日志」,搜索该应用的请求记录,获取具体错误详情
5. 第三方Cmdlet异常
Invoke-MSCloudIdMSGraphQuery属于第三方PowerShell模块(如MSCloudIdAssessment),并非微软官方工具。模块版本过期或自身逻辑问题,都可能导致请求失败。
排查方式:
- 更新对应模块:
Update-Module MSCloudIdAssessment - 替换为官方调用方式,直接用
Invoke-RestMethod请求:
$headers = @{Authorization = "Bearer $token"} $users = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/users?filter=signInActivity/lastSignInDateTime le $SignInDate&`$select=displayName,userPrincipalName,onPremisesSamAccountName" -Headers $headers $users.value | Where-Object userPrincipalName -like '*@placeholder.uk' | Export-CSV C:\temp\AZusersinactive.csv -NoTypeInformation
内容的提问来源于stack exchange,提问作者AzureNoob

