Cannot set npm config keys containing underscores (registry auth tokens, for example) via npm_config_ environment variables


(Martin Kühl) #1

The issue is essentially a copy of Issue #15565 (which I can’t link because I’m a new user), where someone suggested I post my analysis here.

What I Wanted to Do

I want to set the environment variable npm_config_//registry.npmjs.org/:_authToken and have npm pick it up as the authentication token for that npm registry.
Example:

env 'npm_config_//registry.npmjs.org/:_authToken=00000000-0000-0000-0000-000000000000' npm publish .

What Happened Instead

npm failed with ENEEDAUTH

Reproduction Steps

env 'npm_config_//registry.npmjs.org/:_authToken=00000000-0000-0000-0000-000000000000' npm publish .

Again, see #15565 for more on reproduction.

Details

Versions:

{ npm: '6.1.0',
  ares: '1.14.0',
  cldr: '33.0',
  http_parser: '2.8.0',
  icu: '61.1',
  modules: '64',
  napi: '3',
  nghttp2: '1.29.0',
  node: '10.4.0',
  openssl: '1.1.0h',
  tz: '2018c',
  unicode: '10.0',
  uv: '1.20.3',
  v8: '6.7.288.43-node.7',
  zlib: '1.2.11' }

I believe the cause for this is the way npm translates environment variables to config keys.

When we have an environment variable npm_config_//registry.npmjs.org/:_authToken,
config reads it from the environment and replaces every _ character with a - character, so the config key would be //registry.npmjs.org/:-authToken,
but then when npm tries to find the token, it looks for a config key for the registry that ends in :_authToken, which fails because the underscore was translated.

So at its root there are two parts of the code that disagree on how config keys should be normalised, and it seems to affect all config keys containing underscores (i.e. none of those can be set using an environment variable).
To fix this I would start by extracting a function that performs this normalisation, and then maybe modify config’s get to normalise all keys prior to lookup.

I hope this can get someone started on a fix?
I’ll happily try to provide one but would need guidance.


(Rebecca Turner) #2

As you note, this is not supported. The usual way to pass in auth tokens via the enviornment is, to add the following to your .npmrc:

//registry.npmjs.org/:_authToken=${AUTH_TOKEN}

And then run:

env 'AUTH_TOKEN=00000000-0000-0000-0000-000000000000' npm publish

Does this meet your needs?


(Martin Kühl) #3

It does not, since that causes every npm command to fail with

Error: Failed to replace env in config: ${AUTH_TOKEN}

as long as that variable is unset; see also https://github.com/npm/npm/issues/15565 and https://github.com/npm/npm/issues/8356.

I’d rather be able to help support using the npm_config_… variable. :slight_smile:


(Rebecca Turner) #4

Yes, that’s certainly true, if used it has to be set.

Historically the fact that auth keys were impossible to round-trip through the environment was considered a feature. That said, I don’t see a justification for that any more.

I would suggest anyone looking to implement this should look at changing the config loader. A change for this should be targeted, perhaps making it so that underscores aren’t translated to hyphens after colons, or something similar.


(Martin Kühl) #5

Thanks for the hint, I’ll give it a shot!

I kept thinking about something along the lines of treating underscores and hyphens identically everywhere, but this more defensive seems like a better idea. :ok_hand:


(system) #6

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.


(Kat Marchán) #7

(Markus Tacker) #9

I started to use this feature and ran into issues with AWS CodeBuild rejecting the environment variable name.

This is not npm’s fault, obviously. And I can work around this by setting the environment variable npm needs from another environment variable which I define in CodeBuild (e.g. NPM_AUTH_TOKEN):

env "npm_config_//registry.npmjs.org/:_authtoken=${NPM_AUTH_TOKEN}" npm whoami

Now, this kinda defeats the purpose of the initial idea.

What if I could provide a simpler environment variable directly which npm would pick up, e.g. npm_config_authtoken, this could be read in getCredentialsByURI() and if present used.


(Kat Marchán) #10

I mean, use it sparingly, but technically the latest npm clients should be able to recognize token= and _authToken= without the registry nerf dart prefix. Though I think that only works for installs right now.


(Markus Tacker) #11

Ok, I will check if it works for install and publish as well.

Which one is more likely to be kept supported in the future? token or _authToken?


(Markus Tacker) #12

Nope, does not work with publish.