pnpm: Cannot authenticate to Github repo during the installation process

When trying to install my packages using a private registry, pnpm goes in error. I think I know what’s going on.

Doing the same via npm works fine because it installs the dependencies that are not in scope from the npm registry and installs the scoped dependencies (the private ones) from the github registry. I could verifying it by checking its package-lock.json

On the other hand, pnpm tries to install ALL the dependencies from one single registry, which is github.

pnpm version: 5.9.3

Code to reproduce the issue:

Code inside .npmrc

registry=https://npm.pkg.github.com/{SCOPE}

I can’t give the information of the log because it contains sensitive information.

Expected behavior:

It should install all the packages.

Actual behavior:

 ERROR  GET https://npm.pkg.github.com/{SCOPE}/bootstrap: Unauthorized - 401
No authorization header was set for the request.

These authorization settings were found:
//npm.pkg.github.com/:_authToken={TOKEN}

Additional information:

Changing .npmrc to the following works fine

{SCOPE}:registry=https://npm.pkg.github.com/{SCOPE}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 27
  • Comments: 80 (22 by maintainers)

Commits related to this issue

Most upvoted comments

We got private package resolving issues too and the last valid version is 7.13.6.

Some context: we use a Gitlab instance on premise and our .npmrc look like:

//gitlab.domain.com/api/v4/packages/npm/:_authToken=AUTH_TOKEN
@team-software:registry=https://gitlab.domain.com/api/v4/packages/npm/

We try to install a library hosted on this gitlab registry: "@team-software/v-components": "0.0.96"

This configuration works with pnpm<=7.13.6 or npm but with pnpm 8.6.6 (and node 20.3.0) we get:

 WARN  GET https://gitlab.domain.com/api/v4/projects/17/packages/npm/@team-software/v-components/-/@team-software/v-components-0.0.96.tgz error (ERR_PNPM_FETCH_404). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://gitlab.domain.com/api/v4/projects/17/packages/npm/@team-software/v-components/-/@team-software/v-components-0.0.96.tgz error (ERR_PNPM_FETCH_404). Will retry in 1 minute. 1 retries left.
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: /builds/.pnpm-store/v3
  Virtual store is at:             node_modules/.pnpm
 ERR_PNPM_FETCH_404  GET https://gitlab.domain.com/api/v4/projects/17/packages/npm/@team-software/v-components/-/@team-software/v-components-0.0.96.tgz: Not Found - 404
 No authorization header was set for the request.

I did some tests:

  • I added //gitlab.domain.com/api/v4/projects/:_authToken=AUTH_TOKEN and this fixed the issue
  • Then I removed //gitlab.domain.com/api/v4/packages/npm/:_authToken=AUTH_TOKEN this brings a new resolving issue. I guess no match between @team-software:registry=xxx and the xxx:_authToken=token
  • I merged both line and used //gitlab.domain.com/api/v4/:_authToken=AUTH_TOKEN, this is working (but doesn’t follow what gitlab recommend to use for npm).

Final:

My understanding is to resolve the package there is a first match on gitlab.domain.com/api/v4/packages/npm/ then a download issued on the url result gitlab.domain.com/api/v4/projects/. Before the header AUTH_TOKEN issued on the first match was forwarded on the “related download” even if there was an uri mismatch?

Just a guess without diving too much how things are working, if someone has more context about this 🙏

I have the following .npmrc:

registry = https://company-artifactory-url.com/artifactory/api/npm/npm/
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}

And til pnpm@7.13 it was working just fine.

I’ve upgraded to v7.14.1 and with the same .npmrc I started getting:

 ERR_PNPM_FETCH_401  GET https://company-artifactory-url.com:443/artifactory/api/npm/npm/@types/react-dom/-/react-dom-17.0.18.tgz: Unauthorized - 401

No authorization header was set for the request.

These authorization settings were found:
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken=eyJ2[hidden]

Downgrading to 7.13 worked well

I am not sure why you all try to include the owner in the registry URL. The docs suggest to use:

@OWNER:registry=https://npm.pkg.github.com

Though this seems to work with npm, so I guess it should works with pnpm as well.

I have the identical issue, this does seem like a long time. ~/.npmrc

//npm.pkg.github.com/:_authToken=ghp_XXXXX
//npmjs.org=true
@1uphealth:registry=https://npm.pkg.github.com/1uphealth

then…

pnpm add @1uphealth/core-1upenv-script
 ERR_PNPM_FETCH_401  GET https://npm.pkg.github.com/1uphealth/@1uphealth%2Fcore-1upenv-script: Unauthorized - 401

No authorization header was set for the request.

These authorization settings were found:
//npm.pkg.github.com/:_authToken=ghp_[hidden]
@1uphealth:registry=https://npm.pkg.github.com/1uphealth

@zkochan FYI I had this config in my global .npmrc:

//registry.npmjs.org:_authToken = ${NPM_TOKEN}
//npm.pkg.github.com:_authToken = ${GITHUB_TOKEN}
@${GITHUB_USER}:registry = https://npm.pkg.github.com

which works with npm install, but breaks pnpm install. The following changes fixed it:

//registry.npmjs.org:_authToken = ${NPM_TOKEN}
//npm.pkg.github.com/:_authToken = ${GITHUB_TOKEN}
@danielbayley:registry = https://npm.pkg.github.com

But I think pnpm should just work exactly like npm from the same configuration…

So, 2 issues it seems:

  1. A trailing / is required before :_authToken=
  2. Environment variables in keys aren’t working (${GITHUB_USER} in this case)

I have the following .npmrc:

registry = https://company-artifactory-url.com/artifactory/api/npm/npm/
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}

And til pnpm@7.13 it was working just fine.

I’ve upgraded to v7.14.1 and with the same .npmrc I started getting:

 ERR_PNPM_FETCH_401  GET https://company-artifactory-url.com:443/artifactory/api/npm/npm/@types/react-dom/-/react-dom-17.0.18.tgz: Unauthorized - 401

No authorization header was set for the request.

These authorization settings were found:
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken=eyJ2[hidden]

Downgrading to 7.13 worked well

I think this will work for you:

registry = https://company-artifactory-url.com/artifactory/api/npm/npm/
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}
//company-artifactory-url.com:443/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}

Duplicating the _authToken entry but including :443 in the second one. Keep both.

I have the following .npmrc:

registry = https://company-artifactory-url.com/artifactory/api/npm/npm/
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}

And til pnpm@7.13 it was working just fine. I’ve upgraded to v7.14.1 and with the same .npmrc I started getting:

 ERR_PNPM_FETCH_401  GET https://company-artifactory-url.com:443/artifactory/api/npm/npm/@types/react-dom/-/react-dom-17.0.18.tgz: Unauthorized - 401

No authorization header was set for the request.

These authorization settings were found:
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken=eyJ2[hidden]

Downgrading to 7.13 worked well

I think this will work for you:

registry = https://company-artifactory-url.com/artifactory/api/npm/npm/
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}
//company-artifactory-url.com:443/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}

Duplicating the _authToken entry but including :443 in the second one. Keep both.

I found that duplicating _authToken_ line with port :443 worked for me, but I think its perhaps a separate issue.

I got into to the situation like this:

  1. Init new project with pnpm
  2. Install some packages from public npm regisry
  3. Notice you now need stuff from private npm registry
  4. Setup everything for that
  5. Now try to install private package
  6. It wont work. The tarball has :443 in the URL so I suspect that could have something to do with the error
  7. Add the extra _authToken line to your .npmrc config.
  8. Now install the private package.
  9. Package is installed succesfully

I was using pnpm version 7.9.3 and 7.27.1 to test this.

Any progress on this please? Haven’t been able to use pnpm because of this for a long time. My situation: .npmrc

@apify-packages:registry=https://npm.pkg.github.com/apify-packages
//npm.pkg.github.com/:_authToken=<token>

pnpm i

 ERR_PNPM_FETCH_401  GET https://npm.pkg.github.com/apify-packages/@apify-packages%2Ffingerprint-injector: Unauthorized - 401

No authorization header was set for the request.

These authorization settings were found:
@apify-packages:registry=https://npm.pkg.github.com/apify-packages
//npm.pkg.github.com/:_authToken=72d4[hidden]
Progress: resolved 1, reused 0, downloaded 0, added 0

Any advice would be highly appreciated.

+1 7.13.6 works and the 7.28.0 didnt work

Alrighty, so I’ve managed to get everything working in GitHub Actions. Below is a list of what I’ve done to get it functional.

I listened to the advice of @brybicki-cyferd https://github.com/pnpm/pnpm/issues/2933#issuecomment-1298586488 and their example with regards to implementing the registry and accounting for the tarball URL:

registry = https://company-artifactory-url.com/artifactory/api/npm/npm/
//company-artifactory-url.com/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}
//company-artifactory-url.com:443/artifactory/api/npm/npm/:_authToken = ${ARTIFACTORY_TOKEN}

Which afterwards gave me an error as I wasn’t able to use a secret in the usual sense. So I instead opted to just implement it in an env like so:

env: 
          PAT: ${{ secrets.PAT }}

This was enough to get the correct authorisation to finally install my private packages.

This was hard to navigate on a few accounts:

  • Documentation is hard to deal with currently
  • #3141 was helpful
  • #5561 helped breakdown some things related to the tarball
  • The new changes referenced regarding security had to be dug via issues and PRs. As well as that, the [release note]
  • (https://github.com/pnpm/pnpm/releases/tag/v7.14.0) was too vague for me to figure out what exactly was going on. This isn’t meant to come across as harsh, I only wanted to point out that the vagueness of these notes weren’t able to help me solve this without pushing further by pestering people on GitHub and Discord
  • The order of using an env was something I hadn’t thought about. This example helped point that out
  • And finally, and this is more of an assumption, using node 14.x was a hindrance as well. This prompted me to make an abrupt upgrade to our node version(we’re readying a big upgrade) to try and get things working.

This was my experience with the getting things going and so I hope that this sheds some light on problems other people might be having. Thanks a bunch @zkochan for their patience and my haranguing about using pnpm.

I’m also open to improving the way I structure my workflows. So if anyone has tips or wants to point some stuff out, then please feel free.

Workflows config:
name: Core Build Pipeline
on:
  pull_request:
    branches:
    - main
jobs:
  build:
    name: CI Build
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v3
      - name: Use Node 15
        uses: actions/setup-node@v3
        with:
          node-version: '15.x'
          registry-url: https://npm.pkg.github.com
      - name: Set registry
        env: 
          PAT: ${{ secrets.PAT }}
        run: |
          echo "@registry_name:registry=https://npm.pkg.github.com/" >> .npmrc
          echo "//npm.pkg.github.com/:_authToken=$PAT" >> .npmrc
          echo "//npm.pkg.github.com:443/:_authToken=$PAT" >> .npmrc
      - uses: pnpm/action-setup@v2.2.4
        name: Install PNPM
        id: pnpm-install
        with:
          version: 7
          run_install: |
            - recursive: true
      - name: Build
        run: |
          pnpm run build 

Rollback pnpm version to 7.11.0 worked to me.

I just had to configure pnpm as well (with pnpm config set) rather than just having .npmrc

github workflow:

name: Publish artifacts
jobs:
  deploy:
    name: Deploy CDK
    runs-on: ubuntu-latest
    env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    permissions:
        packages: read
        contents: read
    steps:
        - uses: pnpm/action-setup@v2
           with:
             version: 8.9.0
              
        - name: Configure PNPM
          run: pnpm config set '//npm.pkg.github.com/:_authToken' "${GITHUB_TOKEN}"
  
        - name: Install dependencies
          run: cd frontend && pnpm install

.npmrc:

@NAMESPACE:registry=https://npm.pkg.github.com

Good news for CodeArtifact users, from AWS’ side this problem has been solved. Quoting a CodeArtifact operation notification all customers who use it got:

You are receiving this notification because your account has recently downloaded an npm or NuGet package from an AWS CodeArtifact repository.

For npm and NuGet packages, CodeArtifact returns URLs in the HTTP response body for certain request types. For example, when the npm install command is run, the npm client will request metadata for each package it needs to install. This metadata contains CodeArtifact URLs that the client will request in order to complete the installation. The same pattern is also used by NuGet clients such as the NuGet CLI and dotnet CLI, and alternate npm clients such as Yarn and pnpm.

Currently these returned CodeArtifact URLs include the HTTPS port number (443) after the hostname, for example [1].

Starting March 27, 2023, CodeArtifact will no longer include the port number in returned URLs, for example [2].

This change will improve compatibility with the pnpm client and make the returned URLs consistent with those returned by the CodeArtifact GetRepositoryEndpoint API. No backward compatibility issues are expected for npm or NuGet clients as a result of the change as the URLs with and without the port number are functionally identical.

There is no impact to Maven and Python packages as these repository protocols do not include CodeArtifact URLs in any response.

If you have any questions or concerns, please reach out to AWS Support [3].

[1] https://domain-123456789012.d.codeartifact.us-west-2.amazonaws.com:443/npm/repo/lodash/-/lodash-4.17.21.tgz [2] https://domain-123456789012.d.codeartifact.us-west-2.amazonaws.com/npm/repo/lodash/-/lodash-4.17.21.tgz [3] https://aws.amazon.com/support

Just complementing what @tlehtimaki said, on my team, we had problems with per project .npmrc. They still get those errors even if they add the _authToken.

The solution was by also adding the _authToken for port 443 in the root level .npmrc (for UNIX users it may be located at ~/.npmrc. Or check it here: https://pnpm.io/cli/config)

Same problem with aws and CodeArtifact aws codeartifact login ... ok pnpm publish works fine

aws codeartifact login ... ok pnpm install @my-scope/my-package fail with

:Unauthorized - 401
No authorization header was set for the request.
These authorization settings were found:
@my-scope:registry=...

pnpm --version 7.25.0

npm 8 works…

Also having this issue on 7.22.0 in combination with gitlab. Rolled back to 7.13.0 which is working fine.

ERR_PNPM_FETCH_404  GET <repo-url> Not Found - 404 No authorization header was set for the request.

I can confirm a regression between 7.13 and 7.14, as well. If I had to take a guess, it would due to how we do auth headers now: https://github.com/pnpm/pnpm/commit/804de211ea299804b9f7d6857eeb93b618856452

I am unsure how to make pnpm to log HTTP requests/responses to dig in further.

Any news?

Edit: Okay, so right after I commented I was about to give up on pnpm but a took another look at npmrc and removed the owner from the github repo url and now pnpm import works for me 🎉 So I had

@owner:register=https://npm.pkg.github.com/owner

and now I have

@owner:register=https://npm.pkg.github.com

And this seems to work on my side.

See if my solution for CodeArtifact can help you guys - https://github.com/pnpm/pnpm/issues/5561#issuecomment-1298565447.

Quite likely given you have :443 in the tarball GET URL but not in the registry URL.

@kraikov I got this to work inside GH Actions by adding the desired repository to the list of allowed action runners. This list is located inside your package settings page. Take this URL as reference to locate this page:

https://github.com/USERNAME/packages/npm/PACKAGE_NAME/settings

On this page, add the desired repository from where you want your GH Action runner to install your private package from.

screenshot

Once that is done, the generated secrets.GITHUB_TOKEN should be able to access the desired package.

For further reference, here is my .npmrc file as well as my workflow file I used to test this:

//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
@OWNER:registry=https://npm.pkg.github.com
name: Foo
on:
  push
env:
  NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
  run: 
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
         uses: actions/checkout@v3
      - name: Install Node.js
         uses: actions/setup-node@v3
         with:
           node-version: 18
      - uses: pnpm/action-setup@v2.0.1
         name: Install pnpm
         id: pnpm-install
         with:
           version: 7

Alternatively, take a look at my testing repository: https://github.com/KuhlTime/pnpm-cannot-authenticate

I hope this will help you 🤞

Hey @zkochan, thanks for the quick reply:

Here is the log from the github actions:

image

And here is the script:

name: Release

on:
  push:
    paths-ignore:
      - '*.md'
    branches:
      - master

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3

      - uses: pnpm/action-setup@v2.2.2
        with:
          version: 6.24.1
          
      - name: Setup Node.js 16.x
        uses: actions/setup-node@v3
        with:
          node-version: 16.x
          registry-url: https://npm.pkg.github.com
          scope: '@opn-ooo'
          always-auth: true

      - name: Install Dependencies
        run: pnpm i -r

      - name: Publish to npm
        run: pnpm -r --workspace-concurrency=1 exec -- npx --no-install semantic-release -e semantic-release-monorepo
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

and here’s the content of .npmrc

strict-peer-dependencies=false
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
@opn-ooo:registry=https://npm.pkg.github.com

I’ve tried to use my own generated PAT with the correct permissions instead of GITHUB_TOKEN - the same result.

I’ve also tried to install pnpm using npm install -g pnpm instead of using the actions. Again - the same result.

Update: hardcoding the PAT instead of getting it from env works

Suspected reason for not sending auth: the resulting “nerf dart” made by pnpm is different than npm’s because of a trailing slash.

pnpm uses the nerf-dart package. When the uri of the registry is passed it’s https://npm.pkg.github.com/statianzo/

function toNerfDart (uri) {
  var parsed = url.parse(uri)
  delete parsed.protocol
  delete parsed.auth
  delete parsed.query
  delete parsed.search
  delete parsed.hash

  return url.resolve(url.format(parsed), '.')
}

npm (6) uses its own implementation within npm-registry-fetch

https://github.com/npm/npm-registry-fetch/blob/d8df0b193b34dad4627db52259322f0dbf9257d2/auth.js#L49-L57

The passed url is https://npm.pkg.github.com/statianzo

Notice no trailing slash. It matters when getting passed to url.resolve

url.resolve('https://npm.pkg.github.com/statianzo/', '.')
// 'https://npm.pkg.github.com/statianzo/'
url.resolve('https://npm.pkg.github.com/statianzo', '.')
// 'https://npm.pkg.github.com/'

The above is with this .npmrc (no trailing slash):

registry=https://npm.pkg.github.com/statianzo