Trusted Publishing (OIDC)
Publish to npm from GitHub Actions or GitLab CI without npm token - npm trusts the CI job through OIDC and adds the provenance of the packages. The setup on npmjs.com, in the CI, for a monorepo, and its limits.
How It Works
With an npm token, anyone who gets the token can publish your packages, until you revoke it. With trusted publishing, you tell npm once which workflow of which repository may publish a package. At each publish, the CI job gets a short-lived OIDC token from GitHub or GitLab proving which repository and workflow it runs, and npm exchanges it for a publish authorization. There is no secret to store nor to rotate.
npm also adds the provenance of the package: its page on npmjs.com links each version to the commit and the run that built it, for a public package published from a public repository.
Relizy needs no option: in a job that can get an OIDC token, without npm token, it publishes to npmjs.org with trusted publishing. With a token too, npm tries OIDC first and falls back to the token.
Setup
1. Publish the First Version
npm cannot create a package with trusted publishing: a new package is published once with an npm token (NPM_TOKEN, see GitHub Actions or GitLab CI), or by hand with npm publish.
2. Add the Trusted Publisher on npmjs.com
On npmjs.com, in the Settings of the package, add a trusted publisher:
- GitHub Actions: the owner and the repository, the file name of the workflow (
release.yml, not its path), and its environment if the job has one. - GitLab CI: the namespace and the project, the top-level pipeline file (
.gitlab-ci.yml, even when the job is in an included file), and its environment if the job has one.
3. Give the Job Its OIDC Token
The workflows generated by relizy init already do it.
jobs:
release:
permissions:
contents: write
# npm trusted publishing (OIDC)
id-token: write
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
# Updates npm to 11.5.1 or later, as the job can request an id token
- uses: relizy/action@v2# The relizy component requests the NPM_ID_TOKEN id token and updates npm
include:
- component: gitlab.com/relizy/relizy/release@2release:
# npm trusted publishing (OIDC)
id_tokens:
NPM_ID_TOKEN:
aud: npm:registry.npmjs.org
before_script:
# Trusted publishing needs npm 11.5.1 or later
- npm install -g npm@latest
# ... install
script:
- pnpm exec relizy release --yesThen remove NPM_TOKEN from the secrets, or keep it for the first publish of the next new packages.
A Monorepo
The trusted publisher is set per package. With npm 11.15 or later, npm trust adds it from the command line, for all the packages in one go (npm asks for your two-factor authentication once, and offers to skip it for the next 5 minutes):
for pkg in @scope/core @scope/utils @scope/vue; do
npm trust github "$pkg" --repo owner/repo --file release.yml --allow-publish --yes
doneOn GitLab: npm trust gitlab "$pkg" --project group/project --file .gitlab-ci.yml --allow-publish --yes. npm trust list <package> shows the trusted publishers of a package. See npm trust.
A new package of the monorepo still needs its first publish with a token: before the bump, Relizy warns about the packages that are not on npm yet (Not on npm yet: ...).
What Relizy Checks
Before the bump, the safety check of the publication does not run npm whoami with trusted publishing (it does not work with OIDC). Instead:
- the npm that publishes must do the OIDC exchange (11.5.1 or later), else the release stops before the bump with the fix. pnpm 10 and earlier publish through npm; pnpm 11 and later publish by themselves.
- the packages that are not on npm yet are listed in a warning: their publish would fail.
Without npm token nor OIDC token in CI, the authentication error tells both ways to publish.
actions/setup-node with a registry-url and without token fills NODE_AUTH_TOKEN with a placeholder (XXXXX-XXXXX-XXXXX-XXXXX): Relizy does not take it for a token. You need no registry-url.
Limits
- npmjs.org only: another registry (GitHub Packages, a private registry) still needs its token.
- Hosted runners only: GitHub-hosted runners and GitLab.com shared runners. npm does not support self-hosted runners yet.
- No provenance for a private repository: the package is published, without provenance.
- Yarn and bun: Relizy does not check their auth, as without trusted publishing. Check that your version supports OIDC, or publish with a token.
See the npm documentation.