GitHub Action 可信发布NPM的OIDC 404陷阱:Node版本与NPM兼容性详解

GitHub Action 可信发布NPM的OIDC 404陷阱:Node版本与NPM兼容性详解

问题现象:反复出现的认证失败

许多开发者在配置 的NPM(OIDC认证)时,都会遇到一个顽固的问题:

 notice Access token expired or revoked. Please try logging in again.

尽管按照官方文档正确配置了OIDC trust relationship,这个错误依然反复出现。

根本原因:Node版本与NPM兼容性

根据npm/cli#8816的讨论,问题的核心在于:

Node.js 25以下版本自带的npm版本过旧,不支持完整的OIDC实现!

版本兼容性矩阵

Node版本 自带npm版本 OIDC支持
Node 25+ npm 10+ ✅ 完全支持
Node 20 npm 9.x ⚠️ 部分支持(可能失败)
Node 18 npm 8.x ❌ 不支持
Node 16 npm 7.x ❌ 不支持

解决方案一:升级Node版本(推荐)

最简单直接的解决方案是升级你的 Actions工作流中的Node版本:

# .github/workflows/publish.yml
name: Publish to NPM

on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write  # OIDC必需
      contents: read
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          # 关键:使用Node 25或更高版本
          node-version: '25.x'
          registry-url: 'https://registry.npmjs.org/'
      
      - run: npm ci
      - run: npm test
      
      - name: Publish to NPM
        run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}  # 传统token作为后备

解决方案二:升级NPM版本(兼容旧Node)

如果你因项目限制必须使用旧版Node,可以在工作流中显式升级npm:

name: Publish to NPM with OIDC

on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write  # 必需:获取OIDC令牌
      contents: read
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js (旧版本)
        uses: actions/setup-node@v4
        with:
          # 使用旧版Node(如Node 18)
          node-version: '18.x'
          registry-url: 'https://registry.npmjs.org/'
      
      # 关键步骤:强制升级到npm 10+
      - name: Upgrade npm to latest
        run: |
          # 查看当前npm版本
          npm --version
          
          # 升级到支持OIDC的最新版本
          npm install -g npm@latest
          
          # 验证升级后的版本
          npm --version
      
      - run: npm ci
      - run: npm test
      
      - name: Publish with OIDC
        run: |
          # 确保使用正确的npm版本
          npm --version
          
          # 使用--provenance启用
          npm publish --provenance --access public

完整的最佳实践配置

1. 正确的OIDC权限配置

在组织或仓库设置中启用正确的权限:

# 工作流文件必须包含这些权限
permissions:
  id-token: write  # OIDC令牌获取
  contents: read   # 代码仓库访问

2. 双重认证策略

为防万一,可以同时配置OIDC和传统token:

- name: Publish with fallback strategy
  run: |
    # 尝试OIDC发布
    if npm publish --provenance --access public; then
      echo "OIDC发布成功"
    else
      echo "OIDC失败,尝试传统token发布"
      echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
      npm publish --access public
    fi

3. 版本检查和验证步骤

在发布前添加验证步骤:

- name: Verify OIDC readiness
  run: |
    echo "Node版本: $(node --version)"
    echo "NPM版本: $(npm --version)"
    
    # 检查npm是否支持provenance
    npm config get provenance || echo "检查provenance支持"
    
    # 验证GitHub Actions环境
    if [ -n "$GITHUB_ACTIONS" ]; then
      echo "运行在GitHub Actions环境中"
    fi

常见错误排查清单

❌ 错误配置

  1. 缺少id-token: write权限
  2. Node版本低于25且未升级npm
  3. npm版本低于10.0.0
  4. 未启用仓库的"读取和写入权限"

✅ 正确配置检查点

  1. [x] permissions中包含id-token: write
  2. [x] Node版本≥25 或 npm版本≥10
  3. [x] 使用actions/setup-node@v4或更高版本
  4. [x] npm publish命令包含--provenance标志
  5. [x] NPM包设置中启用了"要求双重认证"

为什么需要OIDC?

传统NPM_TOKEN方式的安全问题:

  • 令牌可能长期有效
  • 可能被意外泄露
  • 权限范围可能过大

OIDC优势:

  • 短期令牌(几分钟有效期)
  • 自动令牌轮换
  • 细粒度权限控制
  • 发布来源可验证(provenance)

总结

NPM OIDC认证的错误通常不是配置问题,而是版本兼容性问题。记住这个简单的规则:

使用Node 25+,或者手动升级npm到10+

这个问题的隐蔽性在于:错误信息没有明确指出是版本问题,而是提示token过期或撤销,导致开发者花费大量时间检查权限配置而不是检查工具版本。

通过确保正确的版本组合,你可以顺利实现NPM的可信发布,享受OIDC带来的安全优势,同时避免令人沮丧的404错误。