一次 npm 更新强制2FA导致的发布失败的排查:403、2FA、Recovery Code、Granular Token 的混乱体验

最近在更新发布自己的一个 npm 包(branch-commit-compare)时踩了一堆坑。问题本身不复杂,但 npm 新旧验证体系在 UI 和流程上混杂一起,导致排查成本远高于必要水平。这里记录一下整个过程,避免别人重复踩坑。


背景

我本地执行:

复制代码
npm publish

结果直接报:

dart 复制代码
npm ERR! 403 Forbidden - PUT https://registry.npmjs.org/xxx
Two-factor authentication or granular access token with bypass 2fa enabled is required to publish packages.

很明确:npm 要求 2FA 或具有 bypass-2FA 权限的 token 才允许发布。问题在于 ------ 我当时的 2FA 状态看起来"不完整"。


一、UI 误导:npm 只给我一个「Security Key」选项

进入 npm 账户的 Security 页面 → Enable 2FA,看到的 2FA 方式只有:

Security Key(USB/NFC、生物识别等)

正常情况下,npm 应该同时提供:

  • Authenticator App(TOTP)
  • Security key(FIDO U2F)
  • Recovery codes

但在我这里,点击 Enable 2FA 直接跳到 Security Key,没有 TOTP 选项

这会带来一个明显问题:

npm CLI 的 --otp=xxxxxx 只能输入 TOTP 码,不能输入恢复码、不能输入 security-key 相关内容。

也就是说:只启用 Security Key = 无法在 CLI 完成 publish


二、我以为自己拿到的是「秘钥」,实际上那是 Recovery Codes

复制代码
e496c18fe4b39b0e2e1d2d4c7958c561fd3a2526f31ce7aea8394413b1826576
061baf4f296ea7e94c416eb9be80ecd47843ae7b957916f7d788d7310cefc053
4c7feaaca38231ca76222bab37eea9ff1dc69ccf90398900025c4dd03226002b
1886537d1acf213f1ea27329bd7ecdc6e6934397a55a1b1d5882698617f738ed
8b6abe5645ffb5e09d6b6aad2955d8ac9c64bf971751845cbf2afd453476473d

UI 只显示一串普通文本,把它描述成"安全密钥"。但实际那是 Recovery Codes(一次性备份码),不是 TOTP Secret,也不是 token。

把换行删掉、合并成一行都没用,它压根不是 TOTP。

这导致我误以为 CLI 能用它 publish → 当然失败。


三、npm profile get 暴露核心真相

执行:

arduino 复制代码
npm profile get

返回:

matlab 复制代码
two-factor auth │ auth-and-writes

含义:

  • 你已经启用了 2FA,但只启用了 写操作保护
  • npm 要求:发布时必须提供 TOTP
  • Recovery Code 和 Security Key 都不能替代 TOTP

结论:你的 2FA 配置不完整,CLI 肯定 403


四、可行的解决路径:创建 Granular Token 并开启 bypass 2FA

既然 npm CLI 强制需要 TOTP,而 UI 又不给你配置 TOTP,那就只能走另一条路:

1. 创建 Granular Access Token

进入 npm → 头像 → Access Tokens → Create New Token

选择:

  • 类型:Granular / Automation Token
  • 权限:选择你要 publish 的包
  • 关键:勾选 "Bypass two-factor authentication"

创建后会出现真正的一次性 token(长字符串),这才是发布用的。

2. 写入本地 ~/.npmrc

bash 复制代码
echo "//registry.npmjs.org/:_authToken=你的token" >> ~/.npmrc

3. 再次发布

复制代码
npm publish

→ 一次通过。


五、根因:npm 的验证系统正在剧烈切换

npm 现在要求:

  • 经典 token 全部废弃
  • granular token 成为唯一可用的 token
  • granular token 默认需要 2FA
  • 而 2FA 又分 TOTP / security key
  • 但 UI 渐进式上线,部分用户只能看到 security key
  • CLI 又要求 TOTP

这就造成一个现象:

你启用了"半套"2FA,UI 显示正常,但 CLI 无法完成发布。


六、最终解决方案总结

  1. npm profile get 显示 auth-and-writes → CLI 必须 OTP
  2. UI 只给你 Security Key,没有 TOTP → CLI 永远无法输入正确 OTP
  3. Recovery Code 不是 OTP → 无效
  4. 唯一可行方法 → 创建带 bypass-2FA 的 granular token
  5. 写入本地 .npmrc 后发布即可

七、给后来者的建议

如果你正在启用 npm 的 2FA:

  • 一定要启用 TOTP(Authenticator App)
    而不是只启用 Security Key (但是官方只给了这种方式)
  • Granular Token 是目前唯一不会踩坑的方式(特别是 CI/CD)
  • 不要被恢复码误导,它不是 OTP
  • 25年12月9号强制必须使用2FA或者绕过2FA的token 我今天12月12太多人在操作了,官网巨卡无比

结语

npm 的验证体系正在重构,UI 不统一、流程半旧半新,是这次踩坑的根本原因。如果你遇到类似的 403 + 要求 2FA,又找不到 TOTP,多半和我一样卡在了"只有 Security Key"这个界面。

解决方法就是:绕开 2FA,使用带 bypass 权限的 granular token 发布

相关推荐
子兮曰13 小时前
OpenClaw入门:从零开始搭建你的私有化AI助手
前端·架构·github
吴仰晖13 小时前
使用github copliot chat的源码学习之Chromium Compositor
前端
1024小神13 小时前
github发布pages的几种状态记录
前端
不像程序员的程序媛15 小时前
Nginx日志切分
服务器·前端·nginx
北原_春希15 小时前
如何在Vue3项目中引入并使用Echarts图表
前端·javascript·echarts
尽意啊15 小时前
echarts树图动态添加子节点
前端·javascript·echarts
吃面必吃蒜15 小时前
echarts 极坐标柱状图 如何定义柱子颜色
前端·javascript·echarts
O_oStayPositive15 小时前
Vue3使用ECharts
前端·javascript·echarts
竹秋…15 小时前
echarts自定义tooltip中的内容
前端·javascript·echarts
宝贝露.15 小时前
Axure引入Echarts图无法正常显示问题
前端·javascript·echarts