How to set npm credentials using `npm login` without reading from stdin?

86,190

Solution 1

TL;DR: Make an HTTP request directly to the registry:

TOKEN=$(curl -s \
  -H "Accept: application/json" \
  -H "Content-Type:application/json" \
  -X PUT --data '{"name": "username_here", "password": "password_here"}' \
  http://your_registry/-/user/org.couchdb.user:username_here 2>&1 | grep -Po \
  '(?<="token": ")[^"]*')

npm set registry "http://your_registry"
npm set //your_registry/:_authToken $TOKEN

Rationale

Behind the scenes npm adduser makes an HTTP request to the registry. Instead of forcing adduser to behave the way you want, you could make the request directly to the registry without going through the cli and then set the auth token with npm set.

The source code suggests that you could make a PUT request to http://your_registry/-/user/org.couchdb.user:your-username with the following payload

{
  name: username,
  password: password
}

and that would create a new user in the registry.

Many thanks to @shawnzhu for having found a more cleaner approach to solve the problem.

Solution 2

npm set //<registry>/:_authToken $TOKEN

Example for Github Package Registry:

npm set //npm.pkg.github.com/:_authToken $GITHUB_TOKEN

This is the simplest solution that I have found.

Solution 3

npm-cli-login allows you to log in to NPM without STDIN.

In order to install run:

npm install -g npm-cli-login

Example usage:

npm-cli-login -u Username -p Password -e [email protected] -r https://your-private-registry-link

Solution 4

I took a slightly different approach that seems to work great still. To begin with, you will need an auth token. This is easily obtainable by locally running npm adduser and then grabbing the generated token from your ~/.npmrc located in your user folder. In order to be authenticated on your ci server this auth token needs to be appended to the registry URL in the user's .npmrc (similar to how it was locally), not the .npmrc located in the repo, so these worked great as script steps in my CI configuration

- echo "//<npm-registry>:8080/:_authToken=$AUTH_TOKEN" > ~/.npmrc
- npm publish

where AUTH_TOKEN is stored as a secret variable in your settings. A good way to test this is to replace npm publish with npm whoami to test and make sure it successfully logged you in.

Here is my entire publish configuration

publish:
  stage: deploy
  only:
    - tags
  script:
    - yarn run build
    - echo "//<npm-registry>:8080/:_authToken=$NPME_AUTH_TOKEN" > ~/.npmrc
    - npm publish
    - echo 'Congrats on your publication!'

I'm using gitlab-ci but I don't see why this wouldn't apply to any ci application.

Solution 5

An expect script worked for me. You need to make sure expect is installed, this command should do it for ubuntu:

apt-get install expect-dev

Your script could look something like this (npm_login_expect):

#!/usr/bin/expect -f

# set our args into variables
set i 0; foreach n $argv {set "p[incr i]" $n}

set timeout 60
#npm login command, add whatever command-line args are necessary
spawn npm login
match_max 100000

expect "Username"    
send "$p1\r"

expect "Password"
send "$p2\r" 

expect "Email"
send "$p3\r"

expect {
   timeout      exit 1
   eof
}

And then call it like this:

expect -f npm_login_expect myuser mypassword "[email protected]"
Share:
86,190

Related videos on Youtube

shawnzhu
Author by

shawnzhu

geek.

Updated on November 14, 2021

Comments

  • shawnzhu
    shawnzhu over 2 years

    I'm trying to automate npm publish inside a Docker container, but I receive an error when the npm login command tries to read the username and email:

    npm login << EOF
    username
    password
    email
    EOF
    

    It works in a Bash terminal, but in a container (without stdin) it shows error:

    Username: Password: npm ERR! cb() never called!
    npm ERR! not ok code 0
    

    According to npm-adduser:

    The username, password, and email are read in from prompts.

    How can I run npm login without using stdin?

    • dokaspar
      dokaspar over 7 years
      Your command actually worked for me, thanks! :) The only thing missing was to add the --repository parameter...
  • shawnzhu
    shawnzhu about 10 years
    Thanks. the root cause is npm adduser always ask for input from stdin which I can't make. Then I found another way which is kind of trick to generate a working ~/.npmrc. see github.com/npm/npm-registry-client/blob/master/lib/…
  • shawnzhu
    shawnzhu over 9 years
    Yes if there is tty that expect can read. my problem is, there's no STDIN nor sudo tty at all.
  • NikG
    NikG over 9 years
    Worked a treat in a chef recipe as well.
  • Adam K Dean
    Adam K Dean over 8 years
    @shawnzu it'd be nice if you'd post the solution for the rest of the internet, as the link you gave uses master instead of a sha, so it's out of date now :(
  • Marc-Andre R.
    Marc-Andre R. over 7 years
    This is clever but doesn't seems to work in my case. We're using ProGet and the output of that command see to only return and object like { "ok":"true" } and no tokens whatsoever. Seems like proget change the response from that command... I'll kept you posted if I found anything.
  • AntouanK
    AntouanK over 7 years
    What if we just want to login, and not add a new user? I get bcak "user exists" with the above PUT request.
  • AntouanK
    AntouanK over 7 years
  • King Midas
    King Midas about 7 years
    If you have already logged in with npm login, the information of the token can be found at file ~/.npmrc in your home folder. Then, with only npm set //your-registry.com/:_authToken="wKaaaaaaaaaaaaaaaaaaaaaaaaa‌​aaaaaaaa="
  • Highriser
    Highriser almost 7 years
    Has anyone else the problem that this solution is not working? I always get "You don't have permission to publish .."
  • Lovey
    Lovey over 6 years
    Not working for me. I keep getting Username: Password: npm ERR! cb() never called!
  • vedo27
    vedo27 almost 5 years
    For some reason the regex did not work for me on the new Github registry. This one fixed it: grep -oP "token\":\"\K\w+")
  • wdlax11
    wdlax11 over 4 years
    this doesnt work for me at all... i have it in my .npmrc file and try npm install still authentication error.
  • JRichardsz
    JRichardsz over 4 years
    what is your nodejs version? Delete the old .npmrc and try again!
  • Chris Stryczynski
    Chris Stryczynski over 4 years
    This gives me an error of user registration disabled when using verdaccio...
  • was_777
    was_777 over 4 years
    I am getting error : spawn npm login npm ERR! wrong # args: should be "eof channelId" while executing "eof" invoked from within "expect { timeout exit 1 eof }" (file "npm_login.sh" line 20)
  • Beto Frega
    Beto Frega about 4 years
    This is the perfect solution
  • Ami Gulzadi
    Ami Gulzadi almost 4 years
    Worked for me, to login to a Nexus private registry without any internet access.
  • ErikE
    ErikE over 3 years
    npm ping has been set up precisely to allow testing connectivity and credentials. Also note that sometimes it's useful to output to a local .npmrc file instead of always putting it in the user's HOME folder—especially to avoid blowing up the user's normal day-to-day configuration just because some automation command was run.
  • Kipras Melnikovas
    Kipras Melnikovas almost 3 years
    note for github actions users: secrets are accessible via ${{ secrets.SECRET_NAME }}, thus you'll need to npm set "//registry.npmjs.org/:_authToken" ${{ secrets.NPM_TOKEN_OR_WHATEVER }}
  • Florian Wendelborn
    Florian Wendelborn over 2 years
    note for docker users: docker build may log the clear-text value of NPM_TOKEN to your console/ci logs. You can avoid this by putting this command into a ./npm-config.sh and executing that instead.