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

创建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 API权限配置
  • Azure配置的通知URL: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:44:51