创建Microsoft Graph订阅API时通知端点验证失败,请求排查
Azure Graph订阅API验证失败问题排查
基础配置信息
- Webhook端点:
https://omstest.shiplogiq.dev/webhook/graph_listener - 订阅请求地址:
https://graph.microsoft.com/v1.0/subscriptions - 订阅请求体:
{ "changeType" : "updated", "notificationUrl": "https://omstest.shiplogiq.dev/webhook/graph_listener", "resource": "users", "expirationDateTime": "2025-03-28T09:00:07Z", "clientState": "SecretClientStateValue" }
- 请求携带Bearer认证令牌
- Azure API权限配置:

- Azure配置的通知URL:

CodeIgniter端点处理代码
public function graph_listener() { // 1) 检查GET参数中的validationToken $validationToken = $this->input->get('validationToken'); if ($validationToken) { header('Content-Type: text/plain'); echo $validationToken; return; // 返回200和令牌 } // 2) 检查POST JSON中的validationToken $postBody = $this->input->raw_input_stream; $postData = json_decode($postBody, true); if (isset($postData['validationToken'])) { header('Content-Type: text/plain'); echo $validationToken; return; // 返回200和令牌 } // 3) 无验证令牌则处理实际通知 $this->handle_graph_notifications($postData); // 4) 返回200告知Graph已处理 http_response_code(200); }
收到的错误响应
{ "error": { "code": "ValidationError", "message": "Subscription validation request failed. Notification endpoint must respond with 200 OK to validation request.", "innerError": { "date": "2025-03-26T13:18:17", "request-id": "b008367a-60a5-4589-86a8-db95c5da9bba", "client-request-id": "b008367a-60a5-4589-86a8-db95c5da9bba" } } }
问题原因与修复方案
1. 代码逻辑错误(核心问题)
在POST验证分支中,错误输出了GET分支定义的$validationToken变量,而POST请求的验证令牌实际存储在$postData['validationToken']中,这会导致POST验证时返回空内容,触发Graph验证失败。
修改POST分支代码:
if (isset($postData['validationToken'])) { header('Content-Type: text/plain'); echo $postData['validationToken']; // 修正为POST数据中的令牌 return; }
2. 排除CodeIgniter CSRF拦截
CodeIgniter默认开启CSRF防护,会拦截未携带CSRF令牌的POST请求。需将Webhook端点加入CSRF白名单,在application/config/config.php中修改:
$config['csrf_exclude_uris'] = array('webhook/graph_listener');
3. 验证端点可达性
用工具(如Postman)模拟GET请求:https://omstest.shiplogiq.dev/webhook/graph_listener?validationToken=test123,确认返回test123且状态码为200,同时确保端点能被公网访问,无防火墙/WAF拦截。
4. 权限确认
从配置图看,已添加User.Read.All应用权限并完成管理员同意,这部分配置正确,需确保请求令牌包含该权限的scopes。
内容的提问来源于stack exchange,提问作者Vishal Dubey
相关产品推荐
相关产品推荐

