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

Node.js中WebPush.sendNotification调用googleapis端点报401授权头错误

Web Push 401错误排查与问题解答

错误信息

WebPushError: Received unexpected response code
    at IncomingMessage.<anonymous> (/Users/sepp/.../node_modules/web-push/src/web-push-lib.js:347:20)
    at IncomingMessage.emit (node:events:406:35)
    at endReadableNT (node:internal/streams/readable:1331:12)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  statusCode: 401,
  headers: {
    'content-type': 'text/plain; charset=utf-8',
    'x-content-type-options': 'nosniff',
    'x-frame-options': 'SAMEORIGIN',
    'x-xss-protection': '0',
    date: 'Wed, 01 Feb 2023 19:57:43 GMT',
    'content-length': '40',
    'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
    connection: 'close'
  },
  body: 'authorization header must be specified.\n',
  endpoint: 'https://fcm.googleapis.com/fcm/send/duj-etc-etc'
}

相关代码

import * as webPush from "web-push";

const subDetails = {
  endpoint: "https://fcm.googleapis.com/fcm/send/duja6etc-etc",
  expirationTime: null,
  keys: {
      p256dh: "BHtwM-etc-etc",
      auth: "aYkx0etc-etc"
  }
}

await webPush.sendNotification(subDetails, "test message");

排查过程

  • 未配置VAPID,调用webPush.generateRequestDetails(pushSub.details, args.msg)查看请求详情,发现请求中无授权头:
    {
      method: 'POST',
      headers: {
        TTL: 2419200,
        'Content-Length': 121,
        'Content-Type': 'application/octet-stream',
        'Content-Encoding': 'aes128gcm'
      },
      body: <Buffer ....>,
      endpoint: 'https://fcm.googleapis.com/fcm/send/duj-etc-etc'
    }
    
  • 本地同时运行前端页面和后端服务器,响应头包含'x-frame-options': 'SAMEORIGIN'
  • Firefox Dev Edition测试正常,但Chrome和Opera GX出现相同401错误;Opera桌面版暂不支持推送,但错误提示指向授权头问题

问题

  1. 本地环境有特殊要求吗?
  2. 需要满足什么条件才会包含授权头?

问题解答

1. 本地环境的特殊要求

本地环境本身无额外强制要求,但需注意两点:

  • HTTPS环境:Chrome等浏览器要求推送服务必须在HTTPS环境下运行(localhost例外,但FCM对本地请求的授权校验更严格),本地开发可使用自签名证书或工具暴露HTTPS地址。
  • 避免跨域iframe加载:响应头包含x-frame-options: SAMEORIGIN,若前端页面被嵌入跨域iframe,可能导致推送订阅凭证无效,影响后端请求的授权逻辑。

2. 包含授权头的条件

要让web-push自动添加授权头,必须满足以下核心条件:

  • 配置VAPID密钥对:Chrome、Edge等使用FCM的浏览器强制要求VAPID(Voluntary Application Server Identification)授权。web-push库仅在配置VAPID后,才会生成并添加Authorization头。配置示例:
    const vapidKeys = {
      publicKey: '你的VAPID公钥',
      privateKey: '你的VAPID私钥'
    };
    
    webPush.setVapidDetails(
      'mailto:你的邮箱地址',
      vapidKeys.publicKey,
      vapidKeys.privateKey
    );
    
  • 订阅凭证有效:确保前端传递的subDetails中endpoint、p256dh、auth均有效且未过期。Firefox允许无VAPID的请求,但Chrome/FCM强制要求,这也是两类浏览器表现差异的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:45:29