berry: [Bug]: Yarn 2 has broken scoped authentication functionality since 2.2.0 version

Self-service

  • I’d be willing to implement a fix

Describe the bug

Since yarn 2.2.0 version

yarn npm login --scope myCompany

Doesn’t work as previous version, which has a correct behavior.

I used to Yarn 2.1.1 in our repository but when upgrade Yarn till 2.4.3 problem appears. Here are steps and results with two different version of Yarn.

To reproduce

Yarn 2.1.1

Prerequisites

~/repository/.yarnrc.yml

npmScopes:
 myCompany:
  npmAlwaysAuth: true
  npmRegistryServer: "https://repo.myCompany.com/api/npm/npm-bld"

yarnPath: .yarn/releases/yarn-2.1.1.cjs

Steps

yarn npm login --scope myCompany

Creates

~/.yarnrc.yml

npmRegistries:
  "https://repo.myCompany.com/api/npm/npm-bld":
  npmAuthToken: <token>

yarn config

Output

➤ YN0000: npmRegistries Map(1) 
    { 'https://repo.myCompany.com/api/npm/npm-bld' => Map(3) 
        { 'npmAlwaysAuth' => false, 'npmAuthIdent' => null, 'npmAuthToken' => '********' } 
    }
➤ YN0000: npmRegistryServer 'https://registry.yarnpkg.com'
➤ YN0000: npmScopes Map(1) 
    { 'myCompany' => Map(5) 
        { 'npmAlwaysAuth' => true, 
        'npmAuthIdent' => null, 
        'npmAuthToken' => null,
        'npmPublishRegistry' => null, 
        'npmRegistryServer' => 'https://repo.myCompany.com/api/npm/npm-bld' 
        }
    }

yarn add @myCompany/coolPackage

Result

Successful authentication and downloading @myCompany/coolPackage package from scoped repository.

Yarn 2.4.3

Prerequisites

~/repository/.yarnrc.yml

npmScopes:
 myCompany:
  npmAlwaysAuth: true
  npmRegistryServer: "https://repo.myCompany.com/api/npm/npm-bld"

yarnPath: .yarn/releases/yarn-2.4.3.cjs

Steps

yarn npm login --scope myCompany

Creates

~/.yarnrc.yml

npmScopes:
  myCompany:
    npmAuthToken: <token>

yarn config

Output

➤ YN0000: npmRegistries                 Map(0) {}
➤ YN0000: npmRegistryServer             'https://registry.yarnpkg.com'
➤ YN0000: npmScopes                     Map(1) 
    { 'myCompany' => Map(5) 
	    {'npmAlwaysAuth' => true, 
		'npmAuthIdent' => null, 
		'npmAuthToken' => null, 
		'npmPublishRegistry' => null, 
		'npmRegistryServer' => 'https://repo.myCompany.com/api/npm/npm-bld' 
		} 
	}

yarn add @myCompany/coolPackage

Result

Internal Error: Invalid authentication (as an anonymous user). Package was no downloaded.

Output

➤ YN0027: @myCompany/coolPackage@unknown can't be resolved to a satisfying range:

Internal Error: Invalid authentication (as an anonymous user)
    at D (/Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:228065)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async v (/Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:229050)
    at async W.resolvers.getCandidates (/Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:240795)
    at async n.getCandidates (/Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:344518)
    at async K (/Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:36928)
    at async /Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:36175
    at async h (/Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:34661)
    at async F (/Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:35850)
    at async /Users/user/repository/.yarn/releases/yarn-2.4.3.cjs:2:39467

➤ Errors happened when preparing the environment required to run this command.

Environment

System:
    OS: macOS 11.5.2
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  Binaries:
    Node: 14.4.0 - /private/var/folders/zn/v8t9q4ln6qg3xsl5z5235nfw0000gn/T/xfs-4ccbb8d6/node
    Yarn: 2.4.3 - /private/var/folders/zn/v8t9q4ln6qg3xsl5z5235nfw0000gn/T/xfs-4ccbb8d6/yarn
    npm: 6.14.13 - /usr/local/bin/npm
  npmPackages:
    jest: 26.2.2 => 26.2.2

Additional context

I suppose that the problem with lost map in ~/.yarnrc.yml according to “npmRegistries” object. Because of lost object:

npmRegistries:
  "https://repo.myCompany.com/api/npm/npm-bld":
  npmAuthToken: <token>

When I had researching this problem I found that this behavior appears in yarn 2.2.0 version.

Please return behavior of yarn 2.1.1 version.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 18
  • Comments: 26 (5 by maintainers)

Most upvoted comments

Reproducible and not stale.

It’s best practice to use an environment variable, rather than hardcoding the token into the .yarnrc.yml file.

What worked for me is the following.

npmRegistryServer: "https://registry.yarnpkg.com"

npmScopes:
  <Your scope (case sensitive!)>:
    npmAlwaysAuth: true
    npmAuthToken: "${NPM_AUTH_TOKEN}"
    npmRegistryServer: https://npm.pkg.github.com

Then of course make sure you export your token before installing the package.

export NPM_AUTH_TOKEN=shhhh

If you are using yarn cache to cache the files in git lfs, you only need to authenticate the first time you download the packages. Once it’s cached, it will just install the package from the cache.

Yarn is an open-source project. If you have a frustrating bug with it you really want to see fixed, I encourage you to investigate it yourselves and open a PR!

Thank you for working on Yarn but we don’t need patronizing. I’ve done my fair share of open source contributions and will contribute in the right circumstances but onboarding to a new open source project is not a trivial ask. In this case I provided a viable workaround as a contribution. The OP also did a quite detailed report which must have took time investment.

If you can’t fix it, so be be it, but I’m within my right to complain about the bug 👍

Update: I’m going to answer my own question here. I’m uncertain how this fix occurred to me, but it’s certainly worth sharing.

The problem was in my existing yarn.lock file that was originally created with Yarn 1.x. For some reason, the package that I was referring to above had an entry in that yarn.lock (expected) which was causing Yarn 3.x to become very, very confused (unexpected). The fix was to go into that yarn.lock file, find the @mycompany/react-native-copier package resolution, and delete it. Then, run yarn install again.

Problem solved.

I think I had to use yarn config set to make it work.

yarn config set -H npmScopes.<scope name>.npmRegistryServer "<REGISTRY_URL>"
yarn config set -H npmScopes.<scope name>.npmAuthToken "<TOKEN>"

which totally sucks and took some time to figure out 😃

yarn config set -H npmScopes.fortawesome.npmRegistryServer "https://npm.fontawesome.com/" && \
  yarn config set -H npmScopes.fortawesome.npmAuthToken "<YOUR_TOKEN>"

Yarn is an open-source project. If you have a frustrating bug with it you really want to see fixed, I encourage you to investigate it yourselves and open a PR!

Few of our core team use authenticated auth, so we usually can’t even try our changes. We rely a lot on your help there.

@x318 , your solution of swapping npmAuthToken: base64(<user>:<pass>) -> npmAuthIdent: base64(<user>:<pass>) worked for me

# .npmrc

@<scope>:registry = https://<url>/
//<url>/:_auth = <token>
always-auth = true

works.

# ~/.yarnrc.yml

npmRegistries:
  //<url>/:
    npmAuthToken: <token>

npmScopes:
  <scope>:
    npmRegistryServer: https://<url>/
    npmAlwaysAuth: true

does not work in any combination (with/without trailing slashes, all in local/home config, with token in npmScopes.<scope>.npmAuthToken and etc).

More over, npm installs without an explicit version, yarn outputs this

>yarn add @<scope>/<package>
➤ YN0027: @<scope>/<package>@unknown can't be resolved to a satisfying range
➤ YN0041: Invalid authentication (as an unknown user)

➤ Errors happened when preparing the environment required to run this command.

with the explicit version

>yarn add @<scope>/<package>@0.3.43
➤ YN0000: ┌ Resolution step
➤ YN0041: │ @<scope>/<package>@npm:0.3.43: Invalid authentication (as an unknown user)
➤ YN0000: └ Completed in 0s 576ms
➤ YN0000: Failed with errors in 0s 581ms
win 11 x64
npm 9.8.1
yarn 3.6.3
node 19.9.0

Had a similar issue in my repo with nexus npm registry. Appears there is some issue with how yarn tries to authenticate or how it is resolves server response. Swapped out npmAuthToken: base64(<user>:<pass>) -> npmAuthIdent: base64(<user>:<pass>) and it worked

There was no time to look into it in more detail, but most likely this part of the code is somehow related to this:

async function getAuthenticationHeader(registry: string, {authType = AuthType.CONFIGURATION, configuration, ident}: {authType?: AuthType, configuration: Configuration, ident: RegistryOptions['ident']}) {
  const effectiveConfiguration = npmConfigUtils.getAuthConfiguration(registry, {configuration, ident});
  const mustAuthenticate = shouldAuthenticate(effectiveConfiguration, authType);

  if (!mustAuthenticate)
    return null;

  const header = await configuration.reduceHook((hooks: Hooks) => {
    return hooks.getNpmAuthenticationHeader;
  }, undefined, registry, {configuration, ident});

  if (header)
    return header;

  if (effectiveConfiguration.get(`npmAuthToken`)) // uses Bearer header
    return `Bearer ${effectiveConfiguration.get(`npmAuthToken`)}`;

  if (effectiveConfiguration.get(`npmAuthIdent`)) { // uses Basic header
    const npmAuthIdent = effectiveConfiguration.get(`npmAuthIdent`);
    if (npmAuthIdent.includes(`:`))
      return `Basic ${Buffer.from(npmAuthIdent).toString(`base64`)}`;
    return `Basic ${npmAuthIdent}`;
  }

  if (mustAuthenticate && authType !== AuthType.BEST_EFFORT) {
    throw new ReportError(MessageName.AUTHENTICATION_NOT_FOUND, `No authentication configured for request`);
  } else {
    return null;
  }
}

Most likely it has something to do with the settings of the package registry itself

I tested this and it worked yarn@3.6.2

<repo>.yarnrc.yml

npmScopes:
  <scope>:
    npmAlwaysAuth: true
    npmRegistryServer: 'https://<url>'

$HOME/.yarnrc.yml

npmRegistries:
  //<url>:
    npmAuthToken: <token>

Is there any workaround to this bug that would allow installation of third-party packages from a private repo? In my case, I’d like to install @fortawesome/fontawesome-pro and I am unable to do so.

I’ve tried every workaround listed in this thread, including adding the information to my ~/.yarnrc.yml to no avail.

Invalid authentication (as an unknown user)

PTAL: https://github.com/yarnpkg/berry/issues/1319

So far you are not able to split configurations for npmScopes between a project configuration and your global configuration in your home directory. Delete the npmScope configuration in your project and define it completely in your global configuration. Then the authentication part should work as well.