最近在更新发布自己的一个 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 无法完成发布。
六、最终解决方案总结
npm profile get显示 auth-and-writes → CLI 必须 OTP- UI 只给你 Security Key,没有 TOTP → CLI 永远无法输入正确 OTP
- Recovery Code 不是 OTP → 无效
- 唯一可行方法 → 创建带 bypass-2FA 的 granular token
- 写入本地
.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 发布。