Posts Tagged plaintext

Getting NPM to prompt for username and password (POC/Hack)

This is an experimental POC hack that seems to be working. I don’t know if I will actually use this anywhere, but I wanted to try it. We use an corporate NTLM proxy at my current place of work and storing plaintext passwords is a non-starter. I am using “cntlm”, which I think is great, but might be hard for some groups in “enterprisey” environments to adopt.

If you want to completely undo this, you’ll probably have to reinstall node.js, which on Windows might require a reboot.

1. Install sync-prompt in the npm-registry-client folder

As we’ll be tinkering with npm, let’s get this out of the way first. “sync-prompt” is a way to synchronously get input at the command prompt from the user. We need this to ask for the user’s credentials, since we wont be storing them.

Go to your nodejs folder and find the npm\node_modules\npm-registry-client folder. Run this command:

npm install sync-prompt

2. Modify npm-registry-client to include our “npmfix” module

The “index.js” for npm-registry-client that npm uses will be in your nodejs install folder under \npm\node_modules\npm-registry-client\index.js.

Add this at the beginning:

var ntlmFix = require('./npmfix.js');

Then at line ~55 or so (after the “var alwaysAuth = this.conf.get(‘always-auth’)) add this line:

this.conf.get = ntlmFix.fix(this.conf.get);

3. Create the npmfix.js in the same folder as the index.js for the npm-registry-client

We need the script below with one change. Change the “proxyHostPort” variable to be the appropriate proxy hostname (ie: myservername) followed by a colon (:), followed by the appropriate port number (ie: 80). If this was made “production ready”, one change would be to use the actual proxy from NPM and add the credentials to it. 

Here’s what we need there:

//npmfix
var prompt = require('sync-prompt').prompt;
var proxyHostPort = "<proxy host>:<proxy port>";
var oldFunc;
var username;
var password;
var credentials;
var hidden = true;
function newFunc(arg) {
if(arg === 'proxy') {
if(!username) {
username = prompt('Username: ');
password = prompt('Password: ', hidden);
credentials = "http://" + encodeURIComponent(username) + ":" + encodeURIComponent(password) + "@" + proxyHostPort + "/";
}
console.log('Overriding proxy ...');
return credentials;
} else {
return oldFunc.apply(this, arguments);
}
}
function fix(getFunc) {
oldFunc = getFunc;

return newFunc;

}
module.exports = {
fix: fix
};

The objective of this code is to wrap the config “get” calls and if “proxy” is asked for, ask for credentials if it’s the first time this session, otherwise use the credentials currently in memory.

4. Set NPM to some junk proxy to make sure it’s working

I use the following command:

npm set proxy http://junk.com:80/

Since I use cntlm, I also turn that off (NET STOP CNTLM).

If you’ve done everything correctly, you should see the same thing I do when you try something like “npm install uglify-js”. If I type my Windows NT credentials (<domain>\<username>) and then my password, it works.

, , , , , ,

Leave a comment