docs: rewrite the authentication settings page in plain language (#17043)

* docs: rewrite the authentication settings page in plain language

A reader reported that pnpm.io/npmrc was hard to follow. The page opened
with a long security-migration section before it described any setting,
packed several rules into each sentence, and mixed pnpm 11 and pnpm 12
history into the v12 page.

- Add a quick start for `pnpm login` and CI.
- Move the environment-variable restriction and the migration options
  after the settings, as a list of alternatives.
- Split the `_auth` rules and its routing priority into lists.
- Drop version history from the prose; "Added in" markers remain.
- Fix the `<URL>:keyfile` code span, which rendered an HTML entity
  literally.
- Group each certificate setting with its per-registry variant.

Each page keeps its own version's behavior: where `pnpm login` saves
tokens, the `_auth` routing priority, and `${NAME?}` support on v11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: drop _auth validation details from the auth settings page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: drop version history from the auth settings page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: group auth settings by the file they go in

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: limit the _auth repository note to _auth

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Zoltan KochanandClaude Opus 5.5 authored and GitHub committed 2026-10-17 16:28:13 +02:00
1 parent 5d03c126be
commit 6beecb0bf0
2 files changed
+400 -325

No files matched your search

+202 -174
View File
@@ -3,111 +3,78 @@ id: npmrc
title: "Authentication Settings"
---
The settings on this page contain sensitive credentials. Most use
npm-compatible INI files; the structured [`_auth`](#_auth) setting lives in the
global YAML config. Do not commit credential files to your repository.
This page covers registry credentials and client certificates. These settings
hold secrets. Keep them out of your repository.
For non-sensitive settings (proxy, SSL, registries, etc.), see [Settings (pnpm-workspace.yaml)](./settings.md).
For other settings, such as proxies and registries, see
[Settings (pnpm-workspace.yaml)](./settings.md).
## Quick start
On your machine, log in to the registry:
```sh
pnpm login
```
pnpm saves the token in the global `config.yaml`, under [`_auth`](#_auth).
In CI, pass the token through an environment variable:
```sh
export pnpm_config__auth='{"https://registry.npmjs.org":{"@":{"authToken":"${NPM_TOKEN}"}}}'
```
## Auth file locations
pnpm reads npm-compatible INI authentication settings from the following
files, in order of priority (highest first):
pnpm reads auth settings from two kinds of files.
1. **`<workspace root>/.npmrc`** — project-level auth. This file should be listed in `.gitignore`.
2. **`<pnpm config>/auth.ini`** — the legacy user-level auth file. pnpm 11
writes login tokens here; pnpm 12.1 and newer writes structured `_auth` to
the global `config.yaml` instead, but continues to read this file.
3. **`~/.npmrc`** — read as a fallback for easier migration from npm. Use the [`npmrcAuthFile`](./settings/other.md#npmrcauthfile) setting to point to a different file.
INI files in npm's `.npmrc` format hold the
[`.npmrc` and `auth.ini` settings](#settings-in-npmrc-and-authini) and the
[certificate settings](#certificate-settings). If a key is set in more than one
file, the first file in this list wins:
The global `config.yaml` may additionally carry pnpm's structured
[`_auth`](#_auth) setting. pnpm 12.1 and newer writes login tokens there.
1. `<workspace root>/.npmrc`, the project file. Add it to `.gitignore`.
2. `<pnpm config>/auth.ini`. `pnpm config set` writes auth keys here.
3. `~/.npmrc`, so credentials you set up for npm keep working. To read a
different file, use the [`npmrcAuthFile`](./settings/other.md#npmrcauthfile)
setting.
The global `<pnpm config>/config.yaml` holds the [`_auth`](#_auth) setting.
`pnpm login` saves tokens there.
The `<pnpm config>` directory is:
* If the **$XDG_CONFIG_HOME** env variable is set: **$XDG_CONFIG_HOME/pnpm/**
* On Windows: **~/AppData/Local/pnpm/config/**
* On macOS: **~/Library/Preferences/pnpm/**
* On Linux: **~/.config/pnpm/**
* `$XDG_CONFIG_HOME/pnpm/`, if `XDG_CONFIG_HOME` is set
* `~/AppData/Local/pnpm/config/` on Windows
* `~/Library/Preferences/pnpm/` on macOS
* `~/.config/pnpm/` on Linux
## Environment variables in auth settings
## Settings in `.npmrc` and `auth.ini`
Values in the **user-level** auth files (`<pnpm config>/auth.ini` and the user `.npmrc`) may reference environment variables using the `${NAME}` syntax:
```ini
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
```
Since v11.5.3, environment variables are **not** expanded in the **project-level** `.npmrc` at the workspace root for the following settings:
* registry and proxy URLs (`registry`, `@scope:registry`, proxy settings);
* URL-scoped keys (keys starting with `//`);
* credential values (`_authToken`, `_auth`, `_password`, `username`, `tokenHelper`, `cert`, `key`).
A setting that contains a `${...}` placeholder in any of these positions is ignored, and pnpm prints a warning. The project `.npmrc` is checked out together with the repository, so expanding environment variables there would allow a malicious repository to exfiltrate secrets from your environment (such as CI tokens) to an attacker-controlled registry during installation ([GHSA-3qhv-2rgh-x77r](https://github.com/pnpm/pnpm/security/advisories/GHSA-3qhv-2rgh-x77r)).
If your project relied on a committed `.npmrc` containing a line like `//registry.npmjs.org/:_authToken=${NPM_TOKEN}`, move the token to a trusted location instead:
* Write the token to the user-level auth file before installing (for example, in a CI step):
```sh
pnpm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
```
`pnpm config set` writes to the global location by default (`<pnpm config>/auth.ini` for auth settings), not to the project `.npmrc`, so the token never ends up in the repository.
* **Set the credential through an environment variable, with no `.npmrc` file at all** (since v11.6). pnpm reads URL-scoped registry settings from `pnpm_config_//…` environment variables:
```sh
env "pnpm_config_//registry.npmjs.org/:_authToken=$NPM_TOKEN" pnpm install
```
The variable name contains `/`, `:`, and `.`, which `export` and the `NAME=value` shell assignment syntax reject as invalid identifiers. Use the `env` utility (as shown above) to pass it to a single command, or set it through a tool that accepts arbitrary variable names (for example, your CI provider's environment settings or Node's `process.env`).
This is the most direct, file-free replacement for a committed `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` line. Because the registry the credential applies to is encoded in the (trusted) variable name, a malicious repository cannot redirect it to another host. Such an environment value overrides the project `.npmrc` but is itself overridden by a command-line option. The `tokenHelper` setting is intentionally not read from environment variables.
* Or keep the `${NPM_TOKEN}` placeholder line, but put it in the user-level `~/.npmrc` (or the file referenced by [`npmrcAuthFile`](./settings/other.md#npmrcauthfile)) instead of the repository.
* In GitHub Actions, `actions/setup-node` with the `registry-url` input writes the auth setting to a user-level `.npmrc` (referenced by the `NPM_CONFIG_USERCONFIG` environment variable, which pnpm honors), so authentication via the `NODE_AUTH_TOKEN` environment variable continues to work.
* If you cannot easily modify each CI pipeline, you may declare the project `.npmrc` trusted by setting a single environment variable in the CI environment (for example, at the organization or workspace level):
```text
PNPM_CONFIG_NPMRC_AUTH_FILE=.npmrc
```
This is the env form of the [`npmrcAuthFile`](./settings/other.md#npmrcauthfile) setting: it makes pnpm read the project's `.npmrc` as the user-level auth file (a relative path is resolved against the working directory), so environment variables in it are expanded as before. Because the trust declaration comes from the environment — not from the repository — a malicious repository cannot set it for you. The npm-style `NPM_CONFIG_USERCONFIG` variable is also honored as a fallback.
:::danger
Only use this in environments that exclusively build trusted repositories. It disables this protection entirely for the checked-out repository, including the restriction that `tokenHelper` may only be set in user-level config.
:::
The same rule applies to **registry and proxy URLs** in a project `.npmrc` (`registry`, `@scope:registry`, `proxy`, `https-proxy`, `http-proxy`). If you used an environment variable to build a registry URL, move the setting to a trusted source — your user-level `~/.npmrc`, or `pnpm config set "<key>" <value>`. If the URL is not secret, you can also write the resolved value directly in the project `.npmrc`, since only `${...}` placeholders are ignored. For registry settings in `pnpm-workspace.yaml`, see [Settings](./settings/dependency-resolution.md#registries).
## Authentication Settings
Set these in one of the INI files listed in
[Auth file locations](#auth-file-locations).
### &lt;URL&gt;&#58;_authToken
Define the authentication bearer token to use when accessing the specified
registry. For example:
The bearer token for a registry:
```ini
//registry.npmjs.org/:_authToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```
You may also use an environment variable. For example:
In a user-level auth file, the value can reference an environment variable:
```ini
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
```
Environment variables are only expanded in user-level auth files, not in the project-level `.npmrc`. See [Environment variables in auth settings](#environment-variables-in-auth-settings).
See [Environment variables in auth settings](#environment-variables-in-auth-settings).
#### Scope-specific auth tokens
Added in: v11.7.0
pnpm can use different auth tokens for different package scopes, even when those scopes point to the same registry URL. Add the package scope after the registry URL in the auth key:
Some registries, such as GitHub Packages, issue a separate token for each
scope. Put the scope after the registry URL in the key:
```ini
@org-a:registry=https://npm.pkg.github.com/
@@ -119,51 +86,52 @@ pnpm can use different auth tokens for different package scopes, even when those
//npm.pkg.github.com/:_authToken=FALLBACK_TOKEN
```
When installing or publishing `@org-a/*`, pnpm uses `ORG_A_TOKEN`; for `@org-b/*`, it uses `ORG_B_TOKEN`. Optionally, packages without a matching scope fall back to the registry-wide token (`FALLBACK_TOKEN` above), when provided.
pnpm sends `ORG_A_TOKEN` for `@org-a/*` packages and `ORG_B_TOKEN` for
`@org-b/*` packages. Other packages from that registry get `FALLBACK_TOKEN`,
if it is set.
On pnpm 11, `pnpm login --registry=https://npm.pkg.github.com --scope=@org-a`
writes the token to the same scope-specific auth key. pnpm 12.1 and newer writes
the equivalent scoped entry under `_auth` in the global `config.yaml` and adds
the scope to that registry's global `registries` declaration.
This is useful for registries (such as GitHub Packages) that issue tokens per organization or per scope. Previously, auth was selected only by registry URL, so two scopes sharing a registry had to share a token.
`pnpm login --registry=https://npm.pkg.github.com --scope=@org-a` saves a
scoped token under [`_auth`](#_auth) in the global `config.yaml`.
### &lt;URL&gt;&#58;tokenHelper
A token helper is an executable that prints a token to stdout. pnpm sends it as `Authorization: Bearer <token>`. If the output starts with one or more ASCII letters and a space, such as `Bearer my-token`, `Basic …`, or `Token abc`, pnpm uses that string as the header value and does not add `Bearer` again. This is for a token that refreshes, where a script can use a refresh token to obtain a new access token.
The path to a program that prints a token. Use it for tokens that expire, so a
script can fetch a fresh one.
`_authToken`, documented above, is only the token. pnpm always adds `Bearer` in front of it. A token helper can print that same raw token, or a full header value that already starts with ASCII letters and a space.
pnpm runs the program and sends its output as `Authorization: Bearer <output>`.
If the output already starts with a word and a space, such as `Bearer abc`,
`Basic abc`, or `Token abc`, pnpm sends it unchanged.
The configuration for the path to the helper must be an absolute path, with no arguments. In order to be secure, it is only permitted to set this value in the user `.npmrc`. Otherwise a project could place a value in a project's local `.npmrc` and run arbitrary executables.
The path must be absolute and take no arguments. pnpm reads `tokenHelper` only
from user-level auth files. A project `.npmrc` could otherwise make pnpm run
any program. Environment variables cannot set it either.
Setting a token helper for the default registry:
For the default registry:
```ini
tokenHelper=/home/ivan/token-generator
```
Setting a token helper for the specified registry:
For a specific registry:
```ini
//registry.corp.com:tokenHelper=/home/ivan/token-generator
```
## Settings in `config.yaml`
### _auth
Added in: v11.10.0
All registry tokens in one value, keyed by registry URL. Use it in CI, where
the `//host/:_authToken` key cannot be an environment variable name on some
runners.
Configures registry authentication as a single structured value, keyed by registry URL. This is an alternative to the many `//host/:_authToken=…` entries and is designed for CI, where the URL-scoped form (whose variable name contains `/`, `:`, and `.`) cannot be passed through an environment variable on some runners.
pnpm reads `_auth` from two places only:
`_auth` is honored **only** from two trusted locations:
* the global `config.yaml`
* the `pnpm_config__auth` environment variable, as JSON
* the **global** pnpm config (`config.yaml`);
* the `pnpm_config__auth` environment variable (for CI).
It is **ignored** in a project `pnpm-workspace.yaml` or `.npmrc`, so a checked-out repository can never supply registry auth.
The value is keyed by registry URL, so each secret is explicitly bound to the host that may receive it. Registry URL keys must use `http` or `https` and must not include credentials, query strings, or fragments. Within each registry URL, `@` means registry-wide (default) credentials, and a package scope such as `@org` binds credentials to that scope on the same host. The only supported credential field is `authToken` (it maps to `_authToken` / bearer auth); the deprecated `basicAuth` / `username` + `password` forms and `tokenHelper` are not accepted here.
A key under a registry URL that does not start with `@` is skipped with a warning, so a field a later pnpm defines does not stop this one. A key that holds an `authToken` object but lacks its `@`, such as `org` for `@org`, is an error.
pnpm ignores `_auth` in `pnpm-workspace.yaml` and `.npmrc`.
In the global `config.yaml`:
@@ -176,121 +144,190 @@ _auth:
authToken: org-token
```
The equivalent environment variable (a JSON string):
The same value as an environment variable:
```sh
export pnpm_config__auth='{"https://registry.npmjs.org":{"@":{"authToken":"npm-token"},"@org":{"authToken":"org-token"}}}'
```
Both `pnpm_config__auth` (lowercase) and `PNPM_CONFIG__AUTH` (all-caps, the convention some CI runners apply) are honored. If both are set, lowercase wins unless it is empty, in which case uppercase is used.
pnpm also reads `PNPM_CONFIG__AUTH`, the all-caps name some CI runners use. If
both are set, the lowercase one wins unless it is empty.
Since v12.7.0, `authToken` values may reference environment variables using the `${NAME}` syntax, in both locations:
The value follows these rules:
```yaml title="config.yaml"
_auth:
https://registry.npmjs.org:
"@":
authToken: ${NPM_TOKEN}
* Each top-level key is an `http` or `https` registry URL, with no
credentials, query string, or fragment.
* Under a URL, `"@"` holds the token for the whole registry. `"@org"` holds the
token for packages in the `@org` scope.
* `authToken` is the only credential field. It is a bearer token.
* `authToken` can reference an environment variable as `${NAME}`.
Each entry also routes packages to its URL. `"@"` makes the URL the default
registry, and `"@org"` sends `@org/*` packages there. The priority of this
routing depends on where the entry comes from:
1. `--registry` and `--@scope:registry` on the command line win.
2. Entries from `pnpm_config__auth` override the `registry` and `registries`
settings. CI can use this to force a proxy registry.
3. Entries from the global `config.yaml` apply only where no `registry` or
`registries` setting chooses a registry. The token is still sent to its own
URL.
`pnpm login` writes here:
* An unscoped login adds an `"@"` entry. It does not change the `registry`
setting.
* A scoped login adds an `"@org"` entry and adds the scope to that URL in the
global `registries` setting. Logging the same scope in to another registry
moves both.
* `pnpm logout` removes the tokens pnpm wrote to `config.yaml` and `auth.ini`.
It keeps the registry settings.
## Environment variables in auth settings
User-level auth files, `<pnpm config>/auth.ini` and `~/.npmrc`, can reference
environment variables as `${NAME}`:
```ini
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
```
Each entry also infers a trusted registry route: `@` routes the default registry (and `pnpm add <pkg>` resolves there), and `@org` routes that scope. Because the credential and its destination host arrive in one trusted value, repo-controlled config cannot redirect the token to a different host.
pnpm does not expand environment variables in the project `.npmrc` for:
Since v12.1.0, `pnpm login` writes the token in this shape. An unscoped login
adds an `@` credential without changing the machine's default registry. A
scoped login adds that scope to the same URL under the global `registries`
setting; logging the scope into another registry moves both its credential and
its route. `pnpm logout` removes credentials pnpm wrote from `config.yaml` and
from the legacy `auth.ini`, while leaving registry routes in place.
* registry and proxy URLs: `registry`, `@scope:registry`, `proxy`,
`https-proxy`, `http-proxy`
* keys that start with `//`
* credentials: `_authToken`, `_auth`, `_password`, `username`, `tokenHelper`,
`cert`, `key`
The `pnpm_config__auth` / `PNPM_CONFIG__AUTH` environment value may deliberately
route a scope or the default registry and overrides repository configuration,
which lets CI mandate a proxy. A route inferred from `_auth` stored in the
global `config.yaml` is only a fallback: an explicit `registry` or `registries`
declaration in `pnpm-workspace.yaml` or the global config wins. The stored
credential still authenticates requests to its URL; it simply does not redirect
packages away from an explicitly selected registry. CLI registry flags remain
the highest-priority route.
pnpm ignores such a setting and prints a warning. The project `.npmrc` comes
with the repository, so a malicious repository could otherwise send your CI
tokens to a registry it controls
([GHSA-3qhv-2rgh-x77r](https://github.com/pnpm/pnpm/security/advisories/GHSA-3qhv-2rgh-x77r)).
Parsing is strict: a malformed value (bad JSON, wrong shape, an invalid registry URL or scope, or an unsupported credential field) fails fast with an error rather than being silently dropped.
### Moving a token out of the project .npmrc
## Certificate Settings
If your repository commits a line such as
`//registry.npmjs.org/:_authToken=${NPM_TOKEN}`, use one of these instead.
Pass the token in an environment variable named after the key:
```sh
env "pnpm_config_//registry.npmjs.org/:_authToken=$NPM_TOKEN" pnpm install
```
Shells cannot `export` this name, because it contains `/`, `:`, and `.`. Use
`env` as above, or set the variable in your CI provider's settings. It
overrides the project `.npmrc`, and a command-line option overrides it.
Or use [`_auth`](#_auth), as in the [quick start](#quick-start).
Or save the token in `<pnpm config>/auth.ini` in a CI step:
```sh
pnpm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
```
Or move the `${NPM_TOKEN}` line to `~/.npmrc`, or to the file that
[`npmrcAuthFile`](./settings/other.md#npmrcauthfile) names.
In GitHub Actions, `actions/setup-node` with the `registry-url` input already
works. It writes a user-level `.npmrc` and points `NPM_CONFIG_USERCONFIG` at
it. pnpm reads that file, so `NODE_AUTH_TOKEN` keeps working.
If you cannot change every CI pipeline, mark the project `.npmrc` as trusted
with one variable in the CI environment:
```text
PNPM_CONFIG_NPMRC_AUTH_FILE=.npmrc
```
This sets [`npmrcAuthFile`](./settings/other.md#npmrcauthfile). pnpm then reads
the project `.npmrc` as the user-level auth file and expands its variables. A
relative path is resolved against the working directory. A repository cannot
set this variable, because it comes from the environment. pnpm also reads
npm's `NPM_CONFIG_USERCONFIG` if this variable is unset.
:::danger
Use this only where every repository you build is trusted. It turns off this
protection for the checked-out repository, including the rule that only
user-level files can set `tokenHelper`.
:::
The same applies to a registry URL built from an environment variable. Move it
to `~/.npmrc` or set it with `pnpm config set "<key>" <value>`. A URL that is
not secret can be written out in the project `.npmrc`. For registries in
`pnpm-workspace.yaml`, see
[`registries`](./settings/dependency-resolution.md#registries).
## Certificate settings
Like the token settings, these go in `.npmrc` or `auth.ini`.
### ca
* Default: **The npm CA certificate**
* Type: **String, Array or null**
The Certificate Authority signing certificate that is trusted for SSL
connections to the registry. Values should be in PEM format (AKA
"Base-64 encoded X.509 (.CER)"). For example:
The certificate authority (CA) certificate to trust for TLS connections to the
registry, in PEM format:
```ini
ca="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----"
```
Set to null to only allow known registrars, or to a specific CA cert to trust
only that specific signing authority.
Multiple CAs can be trusted by specifying an array of certificates:
To trust several CAs, use an array:
```ini
ca[]="..."
ca[]="..."
```
See also the [`strictSsl`](./settings/network.md#strictssl) setting.
Set it to `null` to trust only the well-known CAs.
See also [`strictSsl`](./settings/network.md#strictssl).
### cafile
* Default: **null**
* Type: **path**
A path to a file containing one or multiple Certificate Authority signing
certificates. Similar to the `ca` setting, but allows for multiple CAs, as well
as for the CA information to be stored in a file instead of being specified via
CLI.
### &lt;URL&gt;&#58;cafile
Define the path to a Certificate Authority file to use when accessing the specified
registry. For example:
```ini
//registry.npmjs.org/:cafile=ca-cert.pem
```
The path to a file with one or more CA certificates. Use it instead of `ca` to
keep the certificates in a file.
### &lt;URL&gt;&#58;ca
Added in: v10.25.0
Define an inline Certificate Authority certificate for the specified registry.
The value must be PEM-encoded, like the global `ca` setting, but it only applies
to the matching registry URL.
A CA certificate in PEM format, trusted only for the given registry:
```ini
//registry.example.com/:ca=-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----
```
### &lt;URL&gt;&#58;cafile
The path to a CA certificate file for the given registry:
```ini
//registry.npmjs.org/:cafile=ca-cert.pem
```
### cert
* Default: **null**
* Type: **String**
A client certificate to pass when accessing the registry. Values should be in
PEM format (AKA "Base-64 encoded X.509 (.CER)"). For example:
The client certificate to send to the registry, in PEM format. The value is
the certificate itself, not a path:
```ini
cert="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----"
```
It is not the path to a certificate file.
### &lt;URL&gt;&#58;cert
Added in: v10.25.0
Define an inline client certificate to use when accessing the specified
registry. Example:
The client certificate to send to the given registry:
```ini
//registry.example.com/:cert=-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----
@@ -298,8 +335,7 @@ registry. Example:
### &lt;URL&gt;&#58;certfile
Define the path to a certificate file to use when accessing the specified
registry. For example:
The path to a client certificate file for the given registry:
```ini
//registry.npmjs.org/:certfile=server-cert.pem
@@ -310,23 +346,16 @@ registry. For example:
* Default: **null**
* Type: **String**
A client key to pass when accessing the registry. Values should be in PEM format
(AKA "Base-64 encoded X.509 (.CER)"). For example:
The client key to send to the registry, in PEM format. The value is the key
itself, not a path. To read the key from a file, use `<URL>:keyfile`.
```ini
key="-----BEGIN PRIVATE KEY-----\nXXXX\nXXXX\n-----END PRIVATE KEY-----"
```
It is not the path to a key file. Use `<URL>&#58;keyfile` if you need to reference
the file system instead of inlining the key.
This setting contains sensitive information. Don't write it to a local `.npmrc` file committed to the repository.
### &lt;URL&gt;&#58;key
Added in: v10.25.0
Define an inline client key for the specified registry URL.
The client key for the given registry:
```ini
//registry.example.com/:key=-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----
@@ -334,8 +363,7 @@ Define an inline client key for the specified registry URL.
### &lt;URL&gt;&#58;keyfile
Define the path to a client key file to use when accessing the specified
registry. For example:
The path to a client key file for the given registry:
```ini
//registry.npmjs.org/:keyfile=server-key.pem
+198 -151
View File
@@ -3,105 +3,80 @@ id: npmrc
title: "Authentication Settings"
---
The settings on this page contain sensitive credentials and are stored in INI-formatted files. Do not commit these files to your repository.
This page covers registry credentials and client certificates. These settings
hold secrets. Keep them out of your repository.
For non-sensitive settings (proxy, SSL, registries, etc.), see [Settings (pnpm-workspace.yaml)](./settings.md).
For other settings, such as proxies and registries, see
[Settings (pnpm-workspace.yaml)](./settings.md).
## Quick start
On your machine, log in to the registry:
```sh
pnpm login
```
pnpm saves the token in `<pnpm config>/auth.ini`. See
[Auth file locations](#auth-file-locations).
In CI, pass the token through an environment variable:
```sh
export pnpm_config__auth='{"https://registry.npmjs.org":{"@":{"authToken":"${NPM_TOKEN}"}}}'
```
## Auth file locations
pnpm reads authentication settings from the following files, in order of priority (highest first):
pnpm reads auth settings from two kinds of files.
1. **`<workspace root>/.npmrc`** — project-level auth. This file should be listed in `.gitignore`.
2. **`<pnpm config>/auth.ini`** — the primary user-level auth file. `pnpm login` writes tokens here.
3. **`~/.npmrc`** — read as a fallback for easier migration from npm. Use the [`npmrcAuthFile`](./settings/other.md#npmrcauthfile) setting to point to a different file.
INI files in npm's `.npmrc` format hold the
[`.npmrc` and `auth.ini` settings](#settings-in-npmrc-and-authini) and the
[certificate settings](#certificate-settings). If a key is set in more than one
file, the first file in this list wins:
1. `<workspace root>/.npmrc`, the project file. Add it to `.gitignore`.
2. `<pnpm config>/auth.ini`. `pnpm login` and `pnpm config set` write auth
keys here.
3. `~/.npmrc`, so credentials you set up for npm keep working. To read a
different file, use the [`npmrcAuthFile`](./settings/other.md#npmrcauthfile)
setting.
The global `<pnpm config>/config.yaml` can hold the [`_auth`](#_auth)
setting.
The `<pnpm config>` directory is:
* If the **$XDG_CONFIG_HOME** env variable is set: **$XDG_CONFIG_HOME/pnpm/**
* On Windows: **~/AppData/Local/pnpm/config/**
* On macOS: **~/Library/Preferences/pnpm/**
* On Linux: **~/.config/pnpm/**
* `$XDG_CONFIG_HOME/pnpm/`, if `XDG_CONFIG_HOME` is set
* `~/AppData/Local/pnpm/config/` on Windows
* `~/Library/Preferences/pnpm/` on macOS
* `~/.config/pnpm/` on Linux
## Environment variables in auth settings
## Settings in `.npmrc` and `auth.ini`
Values in the **user-level** auth files (`<pnpm config>/auth.ini` and the user `.npmrc`) may reference environment variables using the `${NAME}` syntax:
```ini
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
```
Since v11.28.0, npm's `${NAME?}` form is supported too. It expands to the value of `NAME`, or to an empty string without a warning when `NAME` is unset. pnpm warns when an empty environment variable removes an auth token, and the warning names the affected key.
Since v11.5.3, environment variables are **not** expanded in the **project-level** `.npmrc` at the workspace root for the following settings:
* registry and proxy URLs (`registry`, `@scope:registry`, proxy settings);
* URL-scoped keys (keys starting with `//`);
* credential values (`_authToken`, `_auth`, `_password`, `username`, `tokenHelper`, `cert`, `key`).
A setting that contains a `${...}` placeholder in any of these positions is ignored, and pnpm prints a warning. The project `.npmrc` is checked out together with the repository, so expanding environment variables there would allow a malicious repository to exfiltrate secrets from your environment (such as CI tokens) to an attacker-controlled registry during installation ([GHSA-3qhv-2rgh-x77r](https://github.com/pnpm/pnpm/security/advisories/GHSA-3qhv-2rgh-x77r)).
If your project relied on a committed `.npmrc` containing a line like `//registry.npmjs.org/:_authToken=${NPM_TOKEN}`, move the token to a trusted location instead:
* Write the token to the user-level auth file before installing (for example, in a CI step):
```sh
pnpm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
```
`pnpm config set` writes to the global location by default (`<pnpm config>/auth.ini` for auth settings), not to the project `.npmrc`, so the token never ends up in the repository.
* **Set the credential through an environment variable, with no `.npmrc` file at all** (since v11.6). pnpm reads URL-scoped registry settings from `pnpm_config_//…` environment variables:
```sh
env "pnpm_config_//registry.npmjs.org/:_authToken=$NPM_TOKEN" pnpm install
```
The variable name contains `/`, `:`, and `.`, which `export` and the `NAME=value` shell assignment syntax reject as invalid identifiers. Use the `env` utility (as shown above) to pass it to a single command, or set it through a tool that accepts arbitrary variable names (for example, your CI provider's environment settings or Node's `process.env`).
This is the most direct, file-free replacement for a committed `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` line. Because the registry the credential applies to is encoded in the (trusted) variable name, a malicious repository cannot redirect it to another host. Such an environment value overrides the project `.npmrc` but is itself overridden by a command-line option. The `tokenHelper` setting is intentionally not read from environment variables.
* Or keep the `${NPM_TOKEN}` placeholder line, but put it in the user-level `~/.npmrc` (or the file referenced by [`npmrcAuthFile`](./settings/other.md#npmrcauthfile)) instead of the repository.
* In GitHub Actions, `actions/setup-node` with the `registry-url` input writes the auth setting to a user-level `.npmrc` (referenced by the `NPM_CONFIG_USERCONFIG` environment variable, which pnpm honors), so authentication via the `NODE_AUTH_TOKEN` environment variable continues to work.
* If you cannot easily modify each CI pipeline, you may declare the project `.npmrc` trusted by setting a single environment variable in the CI environment (for example, at the organization or workspace level):
```text
PNPM_CONFIG_NPMRC_AUTH_FILE=.npmrc
```
This is the env form of the [`npmrcAuthFile`](./settings/other.md#npmrcauthfile) setting: it makes pnpm read the project's `.npmrc` as the user-level auth file (a relative path is resolved against the working directory), so environment variables in it are expanded as before. Because the trust declaration comes from the environment — not from the repository — a malicious repository cannot set it for you. The npm-style `NPM_CONFIG_USERCONFIG` variable is also honored as a fallback.
:::danger
Only use this in environments that exclusively build trusted repositories. It disables this protection entirely for the checked-out repository, including the restriction that `tokenHelper` may only be set in user-level config.
:::
The same rule applies to **registry and proxy URLs** in a project `.npmrc` (`registry`, `@scope:registry`, `proxy`, `https-proxy`, `http-proxy`). If you used an environment variable to build a registry URL, move the setting to a trusted source — your user-level `~/.npmrc`, or `pnpm config set "<key>" <value>`. If the URL is not secret, you can also write the resolved value directly in the project `.npmrc`, since only `${...}` placeholders are ignored. For registry settings in `pnpm-workspace.yaml`, see [Settings](./settings/dependency-resolution.md#registries).
## Authentication Settings
Set these in one of the INI files listed in
[Auth file locations](#auth-file-locations).
### &lt;URL&gt;&#58;_authToken
Define the authentication bearer token to use when accessing the specified
registry. For example:
The bearer token for a registry:
```ini
//registry.npmjs.org/:_authToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```
You may also use an environment variable. For example:
In a user-level auth file, the value can reference an environment variable:
```ini
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
```
Environment variables are only expanded in user-level auth files, not in the project-level `.npmrc`. See [Environment variables in auth settings](#environment-variables-in-auth-settings).
See [Environment variables in auth settings](#environment-variables-in-auth-settings).
#### Scope-specific auth tokens
Added in: v11.7.0
pnpm can use different auth tokens for different package scopes, even when those scopes point to the same registry URL. Add the package scope after the registry URL in the auth key:
Some registries, such as GitHub Packages, issue a separate token for each
scope. Put the scope after the registry URL in the key:
```ini
@org-a:registry=https://npm.pkg.github.com/
@@ -113,48 +88,52 @@ pnpm can use different auth tokens for different package scopes, even when those
//npm.pkg.github.com/:_authToken=FALLBACK_TOKEN
```
When installing or publishing `@org-a/*`, pnpm uses `ORG_A_TOKEN`; for `@org-b/*`, it uses `ORG_B_TOKEN`. Optionally, packages without a matching scope fall back to the registry-wide token (`FALLBACK_TOKEN` above), when provided.
pnpm sends `ORG_A_TOKEN` for `@org-a/*` packages and `ORG_B_TOKEN` for
`@org-b/*` packages. Other packages from that registry get `FALLBACK_TOKEN`,
if it is set.
`pnpm login --registry=https://npm.pkg.github.com --scope=@org-a` writes the token to the same scope-specific auth key.
This is useful for registries (such as GitHub Packages) that issue tokens per organization or per scope. Previously, auth was selected only by registry URL, so two scopes sharing a registry had to share a token.
`pnpm login --registry=https://npm.pkg.github.com --scope=@org-a` saves the
token under the same scoped key.
### &lt;URL&gt;&#58;tokenHelper
A token helper is an executable that prints a token to stdout. pnpm sends it as `Authorization: Bearer <token>`. If the output starts with one or more ASCII letters and a space, such as `Bearer my-token`, `Basic …`, or `Token abc`, pnpm uses that string as the header value and does not add `Bearer` again. This is for a token that refreshes, where a script can use a refresh token to obtain a new access token.
The path to a program that prints a token. Use it for tokens that expire, so a
script can fetch a fresh one.
`_authToken`, documented above, is only the token. pnpm always adds `Bearer` in front of it. A token helper can print that same raw token, or a full header value that already starts with ASCII letters and a space.
pnpm runs the program and sends its output as `Authorization: Bearer <output>`.
If the output already starts with a word and a space, such as `Bearer abc`,
`Basic abc`, or `Token abc`, pnpm sends it unchanged.
The configuration for the path to the helper must be an absolute path, with no arguments. In order to be secure, it is only permitted to set this value in the user `.npmrc`. Otherwise a project could place a value in a project's local `.npmrc` and run arbitrary executables.
The path must be absolute and take no arguments. pnpm reads `tokenHelper` only
from user-level auth files. A project `.npmrc` could otherwise make pnpm run
any program. Environment variables cannot set it either.
Setting a token helper for the default registry:
For the default registry:
```ini
tokenHelper=/home/ivan/token-generator
```
Setting a token helper for the specified registry:
For a specific registry:
```ini
//registry.corp.com:tokenHelper=/home/ivan/token-generator
```
## Settings in `config.yaml`
### _auth
Added in: v11.10.0
All registry tokens in one value, keyed by registry URL. Use it in CI, where
the `//host/:_authToken` key cannot be an environment variable name on some
runners.
Configures registry authentication as a single structured value, keyed by registry URL. This is an alternative to the many `//host/:_authToken=…` entries and is designed for CI, where the URL-scoped form (whose variable name contains `/`, `:`, and `.`) cannot be passed through an environment variable on some runners.
pnpm reads `_auth` from two places only:
`_auth` is honored **only** from two trusted locations:
* the global `config.yaml`
* the `pnpm_config__auth` environment variable, as JSON
* the **global** pnpm config (`config.yaml`);
* the `pnpm_config__auth` environment variable (for CI).
It is **ignored** in a project `pnpm-workspace.yaml` or `.npmrc`, so a checked-out repository can never supply registry auth.
The value is keyed by registry URL, so each secret is explicitly bound to the host that may receive it. Registry URL keys must use `http` or `https` and must not include credentials, query strings, or fragments. Within each registry URL, `@` means registry-wide (default) credentials, and a package scope such as `@org` binds credentials to that scope on the same host. The only supported credential field is `authToken` (it maps to `_authToken` / bearer auth); the deprecated `basicAuth` / `username` + `password` forms and `tokenHelper` are not accepted here.
A key under a registry URL that does not start with `@` is skipped with a warning, so a field a later pnpm defines does not stop this one. A key that holds an `authToken` object but lacks its `@`, such as `org` for `@org`, is an error.
pnpm ignores `_auth` in `pnpm-workspace.yaml` and `.npmrc`.
In the global `config.yaml`:
@@ -167,105 +146,182 @@ _auth:
authToken: org-token
```
The equivalent environment variable (a JSON string):
The same value as an environment variable:
```sh
export pnpm_config__auth='{"https://registry.npmjs.org":{"@":{"authToken":"npm-token"},"@org":{"authToken":"org-token"}}}'
```
Both `pnpm_config__auth` (lowercase) and `PNPM_CONFIG__AUTH` (all-caps, the convention some CI runners apply) are honored. If both are set, lowercase wins unless it is empty, in which case uppercase is used.
pnpm also reads `PNPM_CONFIG__AUTH`, the all-caps name some CI runners use. If
both are set, the lowercase one wins unless it is empty.
Each entry also infers a trusted registry route: `@` routes the default registry (and `pnpm add <pkg>` resolves there), and `@org` routes that scope. Because the credential and its destination host arrive in one trusted value, repo-controlled config cannot redirect the token to a different host.
The value follows these rules:
Precedence, from highest to lowest:
* Each top-level key is an `http` or `https` registry URL, with no
credentials, query string, or fragment.
* Under a URL, `"@"` holds the token for the whole registry. `"@org"` holds the
token for packages in the `@org` scope.
* `authToken` is the only credential field. It is a bearer token.
* `authToken` can reference an environment variable as `${NAME}`.
1. CLI flags (`--registry`, `--@scope:registry`)
2. `pnpm_config__auth` / `PNPM_CONFIG__AUTH`
3. global `config.yaml` `_auth`
Each entry also routes packages to its URL. `"@"` makes the URL the default
registry, and `"@org"` sends `@org/*` packages there. This routing has the
following priority, highest first:
1. `--registry` and `--@scope:registry` on the command line
2. `pnpm_config__auth` or `PNPM_CONFIG__AUTH`
3. `_auth` in the global `config.yaml`
4. `pnpm-workspace.yaml`
Parsing is strict: a malformed value (bad JSON, wrong shape, an invalid registry URL or scope, or an unsupported credential field) fails fast with an error rather than being silently dropped.
## Environment variables in auth settings
Since v11.28.0, environment variable placeholders such as `${NPM_TOKEN}` in an `authToken` value are expanded in both locations.
User-level auth files, `<pnpm config>/auth.ini` and `~/.npmrc`, can reference
environment variables as `${NAME}`:
## Certificate Settings
```ini
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
```
npm's `${NAME?}` form works too. It expands to an empty string
when `NAME` is unset, without a warning. If an empty variable removes an auth
token, pnpm prints a warning that names the key.
pnpm does not expand environment variables in the project `.npmrc` for:
* registry and proxy URLs: `registry`, `@scope:registry`, `proxy`,
`https-proxy`, `http-proxy`
* keys that start with `//`
* credentials: `_authToken`, `_auth`, `_password`, `username`, `tokenHelper`,
`cert`, `key`
pnpm ignores such a setting and prints a warning. The project `.npmrc` comes
with the repository, so a malicious repository could otherwise send your CI
tokens to a registry it controls
([GHSA-3qhv-2rgh-x77r](https://github.com/pnpm/pnpm/security/advisories/GHSA-3qhv-2rgh-x77r)).
### Moving a token out of the project .npmrc
If your repository commits a line such as
`//registry.npmjs.org/:_authToken=${NPM_TOKEN}`, use one of these instead.
Pass the token in an environment variable named after the key:
```sh
env "pnpm_config_//registry.npmjs.org/:_authToken=$NPM_TOKEN" pnpm install
```
Shells cannot `export` this name, because it contains `/`, `:`, and `.`. Use
`env` as above, or set the variable in your CI provider's settings. It
overrides the project `.npmrc`, and a command-line option overrides it.
Or use [`_auth`](#_auth), as in the [quick start](#quick-start).
Or save the token in `<pnpm config>/auth.ini` in a CI step:
```sh
pnpm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
```
Or move the `${NPM_TOKEN}` line to `~/.npmrc`, or to the file that
[`npmrcAuthFile`](./settings/other.md#npmrcauthfile) names.
In GitHub Actions, `actions/setup-node` with the `registry-url` input already
works. It writes a user-level `.npmrc` and points `NPM_CONFIG_USERCONFIG` at
it. pnpm reads that file, so `NODE_AUTH_TOKEN` keeps working.
If you cannot change every CI pipeline, mark the project `.npmrc` as trusted
with one variable in the CI environment:
```text
PNPM_CONFIG_NPMRC_AUTH_FILE=.npmrc
```
This sets [`npmrcAuthFile`](./settings/other.md#npmrcauthfile). pnpm then reads
the project `.npmrc` as the user-level auth file and expands its variables. A
relative path is resolved against the working directory. A repository cannot
set this variable, because it comes from the environment. pnpm also reads
npm's `NPM_CONFIG_USERCONFIG` if this variable is unset.
:::danger
Use this only where every repository you build is trusted. It turns off this
protection for the checked-out repository, including the rule that only
user-level files can set `tokenHelper`.
:::
The same applies to a registry URL built from an environment variable. Move it
to `~/.npmrc` or set it with `pnpm config set "<key>" <value>`. A URL that is
not secret can be written out in the project `.npmrc`. For registries in
`pnpm-workspace.yaml`, see
[`registries`](./settings/dependency-resolution.md#registries).
## Certificate settings
Like the token settings, these go in `.npmrc` or `auth.ini`.
### ca
* Default: **The npm CA certificate**
* Type: **String, Array or null**
The Certificate Authority signing certificate that is trusted for SSL
connections to the registry. Values should be in PEM format (AKA
"Base-64 encoded X.509 (.CER)"). For example:
The certificate authority (CA) certificate to trust for TLS connections to the
registry, in PEM format:
```ini
ca="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----"
```
Set to null to only allow known registrars, or to a specific CA cert to trust
only that specific signing authority.
Multiple CAs can be trusted by specifying an array of certificates:
To trust several CAs, use an array:
```ini
ca[]="..."
ca[]="..."
```
See also the [`strictSsl`](./settings/network.md#strictssl) setting.
Set it to `null` to trust only the well-known CAs.
See also [`strictSsl`](./settings/network.md#strictssl).
### cafile
* Default: **null**
* Type: **path**
A path to a file containing one or multiple Certificate Authority signing
certificates. Similar to the `ca` setting, but allows for multiple CAs, as well
as for the CA information to be stored in a file instead of being specified via
CLI.
### &lt;URL&gt;&#58;cafile
Define the path to a Certificate Authority file to use when accessing the specified
registry. For example:
```ini
//registry.npmjs.org/:cafile=ca-cert.pem
```
The path to a file with one or more CA certificates. Use it instead of `ca` to
keep the certificates in a file.
### &lt;URL&gt;&#58;ca
Added in: v10.25.0
Define an inline Certificate Authority certificate for the specified registry.
The value must be PEM-encoded, like the global `ca` setting, but it only applies
to the matching registry URL.
A CA certificate in PEM format, trusted only for the given registry:
```ini
//registry.example.com/:ca=-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----
```
### &lt;URL&gt;&#58;cafile
The path to a CA certificate file for the given registry:
```ini
//registry.npmjs.org/:cafile=ca-cert.pem
```
### cert
* Default: **null**
* Type: **String**
A client certificate to pass when accessing the registry. Values should be in
PEM format (AKA "Base-64 encoded X.509 (.CER)"). For example:
The client certificate to send to the registry, in PEM format. The value is
the certificate itself, not a path:
```ini
cert="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----"
```
It is not the path to a certificate file.
### &lt;URL&gt;&#58;cert
Added in: v10.25.0
Define an inline client certificate to use when accessing the specified
registry. Example:
The client certificate to send to the given registry:
```ini
//registry.example.com/:cert=-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----
@@ -273,8 +329,7 @@ registry. Example:
### &lt;URL&gt;&#58;certfile
Define the path to a certificate file to use when accessing the specified
registry. For example:
The path to a client certificate file for the given registry:
```ini
//registry.npmjs.org/:certfile=server-cert.pem
@@ -285,23 +340,16 @@ registry. For example:
* Default: **null**
* Type: **String**
A client key to pass when accessing the registry. Values should be in PEM format
(AKA "Base-64 encoded X.509 (.CER)"). For example:
The client key to send to the registry, in PEM format. The value is the key
itself, not a path. To read the key from a file, use `<URL>:keyfile`.
```ini
key="-----BEGIN PRIVATE KEY-----\nXXXX\nXXXX\n-----END PRIVATE KEY-----"
```
It is not the path to a key file. Use `<URL>&#58;keyfile` if you need to reference
the file system instead of inlining the key.
This setting contains sensitive information. Don't write it to a local `.npmrc` file committed to the repository.
### &lt;URL&gt;&#58;key
Added in: v10.25.0
Define an inline client key for the specified registry URL.
The client key for the given registry:
```ini
//registry.example.com/:key=-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----
@@ -309,8 +357,7 @@ Define an inline client key for the specified registry URL.
### &lt;URL&gt;&#58;keyfile
Define the path to a client key file to use when accessing the specified
registry. For example:
The path to a client key file for the given registry:
```ini
//registry.npmjs.org/:keyfile=server-key.pem