NPM Trusted Publishing
Overview
Set up secure npm publishing from GitHub Actions using OIDC trusted publishing instead of long-lived NPM_TOKEN secrets.
When to Use
-
Setting up npm publish workflow in GitHub Actions
-
Migrating from NPM_TOKEN to trusted publishing
-
Adding provenance attestations to packages
-
Publishing monorepo packages
Quick Reference
Requirement Implementation
GitHub Actions permission id-token: write
package.json field repository.url matching GitHub repo
npm publish flag --provenance
npmjs.com setup Configure trusted publisher per package
Implementation
- GitHub Actions Workflow
permissions: contents: write id-token: write # Required for OIDC
jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- run: npm ci
- run: npm run build
# No NODE_AUTH_TOKEN needed - uses OIDC
- run: npm publish --access public --provenance
2. package.json Repository Field
{ "name": "@scope/package", "repository": { "type": "git", "url": "git+https://github.com/owner/repo.git", "directory": "packages/subpackage" } }
Monorepo note: Include directory field for packages not at repo root.
- npmjs.com Configuration
For each package, go to Settings > Publishing access and add:
-
Repository: owner/repo
-
Workflow: publish.yml (or your workflow filename)
-
Environment: (optional)
Common Mistakes
Mistake Fix
Missing --provenance flag Add to npm publish command
Wrong URL format Use git+https://github.com/...
Missing id-token: write
Add to workflow permissions
Forgot npmjs.com setup Configure trusted publisher in package settings
Using NODE_AUTH_TOKEN Remove - OIDC handles auth
Outdated npm version Add npm install -g npm@latest step (see below)
npm Version Requirement
GitHub Actions runners may have an outdated npm version that doesn't properly support OIDC trusted publishing. This causes a confusing error:
npm notice Access token expired or revoked. Please try logging in again. npm error code E404 npm error 404 Not Found - PUT https://registry.npmjs.org/@scope%2fpackage - Not found
Solution: Update npm to latest before publishing:
-
uses: actions/setup-node@v4 with: node-version: "20" registry-url: "https://registry.npmjs.org"
-
name: Update npm to latest run: npm install -g npm@latest
-
run: npm publish --access public --provenance
See GitHub Community Discussion #173102 for details.
Reference