使用C#调用Microsoft Graph API执行条件访问策略评估时遭遇BadRequest错误的求助
C#调用Microsoft Graph API执行条件访问策略评估时遭遇BadRequest错误的求助
我正在尝试用C#结合Microsoft Graph API和Microsoft.Graph NuGet包执行条件访问策略评估(Conditional Access Evaluation)(注意:不是创建或更新策略),但所有请求都返回HTTP 400 BadRequest错误。其他Graph请求(比如获取条件访问策略列表)能正常工作,说明认证没有问题。
代码实现
条件访问评估方法
public async Task<CumulativePolicySettings> RunConditionalAccessWhatIfAsync(string _userId, List<string> _includedApplications) { try { Logger.Information($"Starting Conditional Access What-If check for user {_userId}", _userId); using var httpClient = await AzureHttpAuthenticationService.GetAuthenticatedHttpClientAsync(); var requestBody = new { signInIdentity = new { userId = _userId }, signInContext = new { includeApplications = _includedApplications }, appliedPoliciesOnly = true }; Logger.Information("request body: " + JsonConvert.SerializeObject(requestBody)); var requestUrl = "https://graph.microsoft.com/beta/identity/conditionalAccess/evaluate"; var requestContent = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync(requestUrl, requestContent); Logger.Information($"HTTP Status Code: {response.StatusCode}"); Logger.Information($"Response Headers: {response.Headers}"); response.EnsureSuccessStatusCode(); // 此处会因400抛出异常,无法获取详细错误内容 var responseContent = await response.Content.ReadAsStringAsync(); Logger.Information(responseContent); var policies = JsonConvert.DeserializeObject<List<ConditionalAccessPolicyResult>>(responseContent); var cumulativeSettings = new CumulativePolicySettings(); foreach (var policy in policies) { cumulativeSettings.AllAppliedControls.AddRange(policy.AppliedControls); foreach (var setting in policy.Settings) { cumulativeSettings.CombinedSettings[setting.Key] = setting.Value; } } Logger.Information("Conditional Access What-If check completed. Policies evaluated: {Count}", policies.Count); return cumulativeSettings; } catch (Exception ex) { Logger.Error("Error occurred during Conditional Access What-If check: {Message}", ex.Message); return null; } }
认证服务实现
private async Task<string> GetAccessTokenAsync() { var app = ConfidentialClientApplicationBuilder.Create(ClientID) .WithClientSecret(ClientSecret) .WithAuthority(Authority) .Build(); string[] Scopes = { "https://graph.microsoft.com/.default" }; var result = await app.AcquireTokenForClient(Scopes).ExecuteAsync(); return result.AccessToken; } public async Task<HttpClient> GetAuthenticatedHttpClientAsync() { var httpClient = new HttpClient(); var token = await GetAccessTokenAsync(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); return httpClient; }
当前请求详情
生成的JSON请求体如下:
{ "signInIdentity":{ "userId":"123c123d-1a88-44a5-93a6-1230d12365b2" }, "signInContext":{ "includeApplications":["00000003-0000-0ff1-ce00-000000000000"] }, "appliedPoliciesOnly":true }
请求返回的日志信息:
2025-06-04 23:15:42.955 +02:00 [INF] HTTP Status Code: BadRequest 2025-06-04 23:15:42.956 +02:00 [INF] Response Headers: Cache-Control: no-cache Transfer-Encoding: chunked Strict-Transport-Security: max-age=31536000 request-id: b30a0e35-0b3c-4274-ae93-977d95ff46dc client-request-id: b30a0e35-0b3c-4274-ae93-977d95ff46dc x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"Germany West Central","Slice":"E","Ring":"4","ScaleUnit":"002","RoleInstance":"FR3PEPF00000351"}} Link: [省略] Deprecation: Thu, 17 Feb 2022 23:59:59 GMT Sunset: Sat, 17 Feb 2024 23:59:59 GMT Date: Wed, 04 Jun 2025 21:15:42 GMT
排查与解决方案
1. 先获取Graph返回的详细错误信息
当前代码在response.EnsureSuccessStatusCode()处会直接抛出异常,导致无法获取Graph返回的具体错误描述(比如哪个字段缺失或格式错误)。建议先读取响应内容再判断请求是否成功:
修改代码中的响应处理部分:
var response = await httpClient.PostAsync(requestUrl, requestContent); Logger.Information($"HTTP Status Code: {response.StatusCode}"); Logger.Information($"Response Headers: {response.Headers}"); // 先读取响应内容,无论状态码是否成功 var responseContent = await response.Content.ReadAsStringAsync(); Logger.Information("Response content: " + responseContent); if (!response.IsSuccessStatusCode) { Logger.Error("Request failed with content: " + responseContent); // 可以根据错误内容做针对性处理 return null; } // 后续正常处理逻辑 var policies = JsonConvert.DeserializeObject<List<ConditionalAccessPolicyResult>>(responseContent); // ...
Graph通常会返回类似如下的错误信息,帮助定位问题:
{ "error": { "code": "BadRequest", "message": "The request body is missing required properties: signInContext.ipAddress", "innerError": { "date": "2025-06-04T21:15:42", "request-id": "b30a0e35-0b3c-4274-ae93-977d95ff46dc", "client-request-id": "b30a0e35-0b3c-4274-ae93-977d95ff46dc" } } }
2. 确保请求体符合Graph API的格式要求
根据Microsoft Graph官方文档,evaluate端点的请求体需要符合conditionalAccessEvaluationRequest类型规范。常见的问题点:
signInContext可能需要补充更多上下文字段(比如ipAddress、userAgent等),仅传递includeApplications可能不足以触发正确的评估逻辑- 确认
includeApplications中的应用ID是有效的(你传递的00000003-0000-0ff1-ce00-000000000000是Exchange Online的ID,格式正确) - 建议使用Microsoft Graph Beta SDK来自动处理序列化,避免手动拼接JSON的错误
3. 使用Microsoft Graph Beta SDK简化请求
手动拼接URL和JSON容易出错,推荐使用Microsoft Graph Beta SDK来封装请求,SDK会自动处理序列化、端点路径和请求头:
步骤1:安装Beta SDK
Install-Package Microsoft.Graph.Beta
步骤2:修改代码使用SDK
using Microsoft.Graph.Beta; using Microsoft.Graph.Beta.Models; public async Task<CumulativePolicySettings> RunConditionalAccessWhatIfAsync(string _userId, List<string> _includedApplications) { try { Logger.Information($"Starting Conditional Access What-If check for user {_userId}", _userId); var graphClient = await AzureHttpAuthenticationService.GetAuthenticatedGraphClientAsync(); var requestBody = new ConditionalAccessEvaluationRequest { SignInIdentity = new ConditionalAccessEvaluationRequestSignInIdentity { UserId = _userId }, SignInContext = new ConditionalAccessEvaluationRequestSignInContext { IncludeApplications = _includedApplications, // 补充必要的上下文字段,示例: IpAddress = "192.168.1.1", UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" }, AppliedPoliciesOnly = true }; var evaluationResult = await graphClient.Identity.ConditionalAccess.Evaluate.PostAsync(requestBody); var cumulativeSettings = new CumulativePolicySettings(); foreach (var policy in evaluationResult.Value) { cumulativeSettings.AllAppliedControls.AddRange(policy.AppliedControls); foreach (var setting in policy.Settings.AdditionalData) { cumulativeSettings.CombinedSettings[setting.Key] = setting.Value; } } Logger.Information("Conditional Access What-If check completed. Policies evaluated: {Count}", evaluationResult.Value.Count); return cumulativeSettings; } catch (Exception ex) { Logger.Error("Error occurred during Conditional Access What-If check: {Message}", ex.Message); return null; } } // 新增获取GraphClient的方法 public async Task<GraphServiceClient> GetAuthenticatedGraphClientAsync() { var token = await GetAccessTokenAsync(); return new GraphServiceClient( new DelegateAuthenticationProvider((requestMessage) => { requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); return Task.CompletedTask; }) ); }
4. 确认权限配置
确保应用注册已添加Policy.Read.All应用权限并获得管理员同意,这个权限是执行条件访问评估的必要权限。
内容来源于stack exchange
相关产品推荐
相关产品推荐

