Set up npm credentials over `npm login` without re

2020-02-20 05:44发布

I'm trying to automate npm publish inside a Docker container but I have trouble when the npm login command tries to read the username and email from prompts:

npm login << EOF
username
password
email
EOF

It works in a Bash terminal but not in a container without stdin open, and shows the following error message:

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.

So how can I run npm login without stdin open?

12条回答
贪生不怕死
2楼-- · 2020-02-20 06:43

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.

查看更多
▲ chillily
3楼-- · 2020-02-20 06:48

Hard to believe that after all this time there is still no solution for npm login. Sure you can grab a token once and use it for all your CI needs, but what about the security implications of a never expiring token? And what if one day admins decide that tokens should expire?

Below is my hacky javascript solution using npm-registry-client package. Just pass a json string argument and it will login and write an .npmrc file into your current dir. To log out use npm logout as usual.

var client = new (require('npm-registry-client'))({});
var std_in = JSON.parse(process.argv[2]);

if (std_in.uri === undefined) {
    console.error('Must input registry uri!');
    return;
}

// fix annoying trailing '/' thing in registry uri
if (std_in.uri[std_in.uri.length - 1] !== '/') {
    std_in.uri = std_in.uri + '/';
}

if (std_in.scope === undefined) {
    console.error('Must input scope!');
    return;
    //std_in.scope = '@my-scope'; // or add default scope of your own
}

if (std_in.scope[0] !== '@') {
    std_in.scope = '@' + std_in.scope;
}

client.adduser(std_in.uri, std_in.params, function(err, data, raw, res) {
    if (err) {
        console.error(err);
        return;
    } 
    require('fs').writeFileSync('.npmrc', `${std_in.scope}:registry=${std_in.uri}\n//${(std_in.uri.split('//'))[1]}:_authToken=${data.token}`);
});

Example input:

{ 
    "uri": "https://my-nmp.reg",
    "scope": "@my-scope",
    "params": {
        "auth": {
            "username": "secret-agent",
            "password": "12345",
            "email": "secret-agent@007.com"
        }
    }
}
查看更多
再贱就再见
4楼-- · 2020-02-20 06:48

One solution is to fetch the token and update the ~/.npmrc

export ARTIFACTORY_TOKEN=`curl --silent --show-error --fail -u $ARTIFACTORY_USERNAME:$ARTIFACTORY_API_KEY https://artifactory.my.io/artifactory/api/npm/auth | \
grep -oP '_auth[\s?]=[\s?]\K(.*)$'`

echo "@my:registry=https://artifactory.my.io/artifactory/api/npm/npm-release-local/" > ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:_auth=${ARTIFACTORY_TOKEN}" >> ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:email=${ARTIFACTORY_USERNAME}" >> ~/.npmrc
echo "//artifactory.my.io/artifactory/api/npm/npm-release-local/:always-auth=true" >> ~/.npmrc

This prevents issues with @scope package retrieval from npmjs

查看更多
forever°为你锁心
5楼-- · 2020-02-20 06:49
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.

查看更多
Explosion°爆炸
6楼-- · 2020-02-20 06:49

For the solution 2 exposed by ke_wa in this duplicated post has worked.

Mashup:

export NPM_USERNAME=mUs34
export NPM_PASSWORD=mypassW0rD
export NPM_EMAIL=user@domain.com
npm adduser<<!
$NPM_USERNAME
$NPM_PASSWORD
$NPM_EMAIL
!
查看更多
Viruses.
7楼-- · 2020-02-20 06:50

You could use an expect script instead or write a node script that uses pty.js.

查看更多
登录 后发表回答