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

Express配置JWT白名单后Stripe webhook请求仍提示未授权

问题根因

Stripe的请求没有命中你配置的JWT白名单,被express-jwt中间件直接拦截返回了未授权错误。
Postman直连能通过校验,是因为直连请求的路径完全符合你写的匹配规则,但Stripe发过来的实际请求存在你没覆盖到的隐性偏差,常见偏差点有三个:

  • 路径格式差异:Stripe后台配置的webhook地址可能带尾斜杠、查询参数,经过反向代理(Nginx、API网关)时还可能被重写拼接额外字符,和你Postman测试的路径不完全一致
  • 依赖库匹配bug:你用的express-unless(express-jwt的unless功能依赖这个库)在混合使用字符串路径、正则、methods限制的配置格式时,部分版本存在正则规则优先级失效的问题,会出现同路径不同来源请求匹配结果不一致的情况
  • 解析顺序冲突:如果把全局JSON解析中间件放在JWT和webhook路由前面,不仅会导致后续Stripe签名校验失败,部分场景下还会干扰中间件的路径匹配逻辑
修复步骤
  1. 替换现有模糊的正则匹配规则,改用自定义函数做白名单判断,从根源避免匹配偏差。临时加一行日志打印Stripe请求的真实路径,方便排查:
const UNSECURED_ROUTES = {
  custom: (req) => {
    // 临时日志,上线可删除,用于确认Stripe请求的真实路径和方法
    console.log('Incoming request:', req.method, req.originalUrl);
    // 放行所有webhook路径,忽略尾斜杠、查询参数差异
    if (req.path.startsWith('/api/v1/webhook')) {
      return true;
    }
    // 保留原有其他白名单规则
    if (req.path === '/api/v1/' && req.method === 'GET') return true;
    if (req.path.startsWith('/api/v1/callback') && ['GET', 'POST'].includes(req.method)) return true;
    return false;
  }
};
  1. 调整中间件挂载顺序,把Stripe webhook需要的原始body解析放在最前面,避免签名校验和路径匹配冲突:
    Stripe的签名校验要求拿到未被解析的原始请求Buffer,不能用全局JSON解析处理后的body,所以必须单独给webhook路由配置raw解析,并且放在JWT中间件之前:
// 1. 先处理webhook路由的原始body解析
app.use('/api/v1/webhook', express.raw({ type: 'application/json' }));
// 2. 再挂载JWT校验中间件
app.use(jwtCheck.unless(UNSECURED_ROUTES));
// 3. 最后挂载全局JSON解析和业务路由
app.use(express.json());
app.use('/api/v1', apiRoutesv1);
  1. 检查Stripe后台配置的webhook地址,确保和Postman测试的地址完全一致,没有多余的尾斜杠、拼写错误,确认线上服务部署的是最新代码,没有旧版本进程缓存。
验证方式

配置生效后重新触发Stripe的webhook测试,查看日志确认请求路径打印正确,白名单命中后就不会再出现credentials_required的报错,请求会正常进入webhook处理逻辑。之前Postman测试出现的签名不匹配问题,也会因为调整了body解析顺序自动修复。

内容的提问来源于stack exchange,提问作者Griff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:45:32